是否有可能使过滤器传递附加值以在scala中映射?

时间:2014-06-19 08:39:42

标签: scala

是否可以让filter在Scala中向map传递额外的值?

myList.filter { e =>
    val anotherVal = someFun(e)
    someFun2(anotherVal) != 'error'
}.map {
    val anotherVal = someFun(e)
    someFun3(antherVal)
}

我打电话给someFun(e)两次。

4 个答案:

答案 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进行从eanotherVal的第一次转换。然后,您可以使用collect转换该集合。您的代码可能如下所示:

myList.map(someFun).collect {
   case anotherVal if someFun2(anotherVal) != "error" =>
      someFun3(anotherVal)
}

或者,您可以像这样继续使用filter

myList.map(someFun)
      .filter(anotherVal => someFun2(anotherVal) != "error")
      .map(someFun3)

您喜欢哪一种取决于口味。