使用单个操作的Scala可迭代地图过滤器

时间:2016-01-05 13:36:42

标签: scala iteration

如何在单个操作中执行Iterable map和filter操作,该操作只返回第一个未产生null的值?

更新1:我需要类似这个例子:

Range
    .inclusive(1, 10)
    .collectFirst({
        var x

        if(Random.nextBoolean())
            x = null
        else
            x = 10 

        case x if x != null => x.toString
    })

可以使用collectFirst完成吗?

更新2 :我已尝试使用可迭代范围的以下内容,但出于某种原因,我收到了匹配错误。

def SomeProcess: Boolean = {
        Random.nextBoolean()
    }

val z =
        Iterator
            .range(1, 10)
            .filter(x => {
                println(x)
                true
            })
            .collectFirst( {
                case x if SomeProcess => x.toString
            })

println(z)

2 个答案:

答案 0 :(得分:1)

正如@Dima提到的那样,collectFirst正走在正确的轨道上。使用部分函数来定义条件以及要对与case语句匹配的项执行的任何类型的转换:

def f: PartialFunction[Any, String] = {
  //        Condition   Transformation
  //         |               |
  case x if x != null => x.toString
}

以下是一些使用示例:

val l = List(1, null, 2, "Hello")
l.collectFirst(f)

res0: Option[String] = Some(1)

val l2 = Vector(null, null, null, 10)
l2.collectFirst(f)

res1: Option[String] = Some(10)

基于问题编辑的更新

我不确定以下哪个选项更适合您要求的内容(我不知道该问题的用例是什么)

// Option 1
Range
  .inclusive(1, 10).map(i => if(Random.nextBoolean()) null else 10)
  .collectFirst({
    case x if x != null => x.toString
  })

// Option 2
Range
  .inclusive(1, 10)
  .collectFirst({
    case x if Random.nextBoolean() => 10.toString
  })

由于

答案 1 :(得分:0)

例如,使用find

val xs = (1 to 5).toArray
Array(1, 2, 3, 4, 5)

xs.find(_ == 6)
Option[Int] = None

xs.find(_ > 2)
Option[Int] = Some(3)

这会产生一个Option,第一个项目包含谓词,否则为None