我有一个列表,我通过调用相应的值计算函数以这种方式组合到一个地图。我使用collection.breakout
来避免创建不必要的中间集合,因为我正在做的是有点组合,并且每一点保存的迭代都有帮助。
我需要从地图中过滤掉某些元组,在我的情况下,值小于0.是否可以将其添加到地图本身而不是之后再执行filter
(因此再次迭代)?
val myMap: Map[Key, Int] = keyList.map(key => key -> computeValue(key))(collection.breakOut)
val myFilteredMap = myMap.filter(_._2 >= 0)
换句话说,我希望一次性理想地获得第二张地图,理想情况下,在map()
的第一次调用中,我会过滤掉我不想要的元组。这有可能吗?
答案 0 :(得分:4)
最好做一个flatMap:
import collection.breakOut
type Key = Int
val keyList = List(-1,0,1,2,3)
def computeValue(i: Int) = i*2
val myMap: Map[Key, Int] =
keyList.flatMap { key =>
val v = computeValue(key)
if (v >= 0) Some(key -> v)
else None
}(breakOut)
您可以使用collect
val myMap: Map[Key, Int] =
keyList.collect {
case key if computeValue(key) >= 0 => key -> computeValue(key)
}(breakOut)
但这需要重新计算computeValue(key)
,这很愚蠢。当您过滤然后地图时,收集会更好。
或制作自己的方法!:
import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike
implicit class EnrichedWithMapfilter[A, Repr](val self: TraversableLike[A, Repr]) extends AnyVal {
def maptofilter[B, That](f: A => B)(p: B => Boolean)(implicit bf: CanBuildFrom[Repr, (A, B), That]): That = {
val b = bf(self.asInstanceOf[Repr])
b.sizeHint(self)
for (x <- self) {
val v = f(x)
if (p(v))
b += x -> f(x)
}
b.result
}
}
val myMap: Map[Key, Int] = keyList.maptofilter(computeValue)(_ >= 0)(breakOut)
答案 1 :(得分:4)
您可以使用foldLeft
:
keyList.foldLeft( Map[Key,Int]() ) {
(map, key) =>
val value = computeValue(key)
if ( value >= 0 ) {
map + (key -> value)
} else {
map
}
}