Scala:具有匹配和副作用的条件产量?

时间:2015-04-10 16:19:47

标签: scala

以下内容的正确语法是什么?

var foo = 0
someIterator.foreach{ x => x.property match {
  case "a" => foo += 1
  case "b" => yield "current foo" + foo
}}

即,我正在尝试迭代someIterator。当它匹配一件事时,它应该通过闭包更新局部变量;当它遇到另一个时,它应该产生一些当前状态的推导到结果迭代器,保留连续迭代的状态。

3 个答案:

答案 0 :(得分:5)

您可以使用Option[String]unliftcollect

  • unlift接受一个返回选项的函数,并将其转换为部分函数。
  • collectmap类似,只是它只考虑定义部分函数的元素。

以下示例演示了该方法:

import Function.unlift

var foo = 0
someIterator.map(_.property).collect(unlift {
  case "a" => foo += 1; None
  case "b" => Some("current foo" + foo)
})

Live Demo

答案 1 :(得分:1)

如果你只想得到foo的最终值,那么你可以使用尾递归,你也不必使用可变变量。

@annotation.tailrec
def f(l: List[Char], foo: Int = 0):Int= {
    if (l == Nil) foo
    else {

      l.head match {
        case 'a' => f(l.tail, foo + 1)
        case 'b' => f(l.tail, foo)
      }
    }
  }
val l1 = List('a','b')

f(l1)

l1: List[Char] = List(a, b)
res0: Int = 1

答案 2 :(得分:1)

您可以使用scanLeft的累加器代替变量:

someIterator.scanLeft((0, None: Option[String])){
  case ((foo, _), "a") => (foo + 1, None) 
  case ((foo, _), "b") => (foo, Some(s"current foo $foo"))
}.map(_._2).flatten

示例:

val someIterator = List("a","a","a","a","b", "a", "a", "b").toIterator

scala> someIterator.scanLeft(...){...}.map(_._2).flatten
res16: Iterator[String] = non-empty iterator

scala> res16.toList
res17: List[String] = List(current foo 4, current foo 6)

因此你仍然有一个迭代器