0

Using two Lists, element wise multiplication of these lists and sum of resultant list can be calculated in following way.

(List1 , List2).zipped.foldLeft(0.0) { case (a, (b, c)) => a + b * c }

How can I preform this operation for two iterators in Scala in an optimal and fast way?

Asif
  • 763
  • 8
  • 18
  • Sorry, I do not understand what is the question. – Luis Miguel Mejía Suárez Sep 07 '20 at 12:48
  • Write a benchmark, otherwise it's just guessing. Iterators might be fast because they could traverse the structure without calculating things twice, but I would avoid any statements about opimality of this or any other solution. Your current one might be close to "optiomal" or at least fast enough. – Mateusz Kubuszok Sep 07 '20 at 12:53
  • 3
    I am also a little bit confused. Apart from the performance part, both `zip` and `fold` are present on Iterators. Not sure what you found confusing about Iterators. The code would look almost identical. Did you implement that and weren't satisfied by it's performance? – sinanspd Sep 07 '20 at 12:56
  • what kind of performance improvement you are looking for memory(are those list are too big) or time complexity? your current implementation look good enough. – Raman Mishra Sep 07 '20 at 13:38
  • @sinanspd I used aboove code and provide Iterator instead of List. But that code is not working – Asif Sep 07 '20 at 14:07
  • @RamanMishra Time complexity – Asif Sep 07 '20 at 14:08

2 Answers2

2
(iterator1 zip iterator2).foldLeft(0.0) { case (a, (b, c)) => a + b * c }

is okay I suppose. If you want to squeeze the last bit of performance out of it, use arrays and a while loop.

Martijn
  • 11,964
  • 12
  • 50
  • 96
1

You can use this piece of code that should work with any collection and any numeric type.
It tries to be efficient by doing everything in one traversal. However, as @Martijn said, if you need it to be the most efficient solution then just use plain Arrays of a primitive type like Int or Double and a while.

def dotProduct[N : Numeric](l1: IterableOnce[N], l2: IterableOnce[N]): N =
  l1.iterator.zip(l2).map {
    case (x, y) => Numeric[N].times(x, y)
  }.sum

(note: this code is intended for 2.13+, for 2.12- you may use Iterable instead of IterableOnce)