Reputation: 391
val list1 : List[String] = List(....)
val list2 : List[String] = List(....)
val filtered = list1.filter(list2.toSet.contains)
When using the code above, will toSet
be called for each item in list1
(in which case I should add another val set2 = list2.toSet
, or does the Scala compiler optimizes this in which case the code above will only run toSet
once?
Upvotes: 2
Views: 71
Reputation: 8529
To make sure it is called once, you can just do:
val list1 : List[String] = List(....)
val list2 : List[String] = List(....)
val s: Set[String] = list2.toSet
val filtered = list1.filter(s.contains)
Having said that, you can use intersect
method:
list1.intersect(list2)
This method is located on a trait called StrictOptimizedSeqOps
, and it has comment in its implementation: // Avoid multiple map lookups
So I guess this is optimized.
Upvotes: 2
Reputation: 170713
There are no optimizations needed, toSet
can only run once:
eta-expansion rules for converting list2.toSet.contains
to a lambda. In this specific case the translation is
list1.filter({
val x1 = list2.toSet
{ (y1: String) => x1.contains(y1) }
})
the argument to a method is evaluated before calling it (except for call-by-name parameters, but this isn't one), and to evaluate this block val x1 = list2.toSet
is executed first and then { (y1: String) => x1.contains(y1) }
is returned.
But of course you can be more explicit if you want.
Upvotes: 4