是否可以让filter
在Scala中向map
传递额外的值?
myList.filter { e =>
val anotherVal = someFun(e)
someFun2(anotherVal) != 'error'
}.map {
val anotherVal = someFun(e)
someFun3(antherVal)
}
我打电话给someFun(e)
两次。
答案 0 :(得分:5)
您可以使用flatMap
:
myList.flatMap { e =>
val anotherVal = someFun(e)
if(someFun2(anotherVal) != 'error') {
Some(someFun3(anotherVal))
}
else None
}
答案 1 :(得分:4)
使用for comprehension,像这样,
for {
e <- myList;
anotherVal = someFun(e) if someFun2(anotherVal) != 'error';
} yield someFun3(antherVal)
更新这实际上是flatMap
的语法糖,但这种语法可能会以某种方式简洁地显示代码。
答案 2 :(得分:2)
方法collect
filter
合并map
:
myList collect ( x => someFun(x) match {
case y if someFun2(y) != "error" => someFun3(y)
})
例如:
scala> val xs = 1 to 36
xs: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, .., 36)
scala> def f1(x: Int): Int = x/2
f1: (x: Int)Int
scala> def f2(x: Int): Int = x%3
f2: (x: Int)Int
scala> def f3(x: Int): Int = x*x
f3: (x: Int)Int
scala> xs collect (x => f1(x) match { case y if f2(y) == 1 => f3(y) })
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 1, 16, 16, 49, 49, 100, 100, 169, 169, 256, 256)
答案 3 :(得分:1)
正如Eastsun所说,collect
是用于同时进行过滤,转换和映射的函数。它接受部分函数 - 一个仅应用于满足某个条件的某些输入的函数。然后它会生成一个只包含该函数结果的新集合。
在您的情况下,您有一个仅在someFun2(anotherVal) != "error"
时应用的部分功能。因此,您可以先在原始集合上使用map
进行从e
到anotherVal
的第一次转换。然后,您可以使用collect
转换该集合。您的代码可能如下所示:
myList.map(someFun).collect {
case anotherVal if someFun2(anotherVal) != "error" =>
someFun3(anotherVal)
}
或者,您可以像这样继续使用filter
。
myList.map(someFun)
.filter(anotherVal => someFun2(anotherVal) != "error")
.map(someFun3)
您喜欢哪一种取决于口味。