首页 > 解决方案 > 如何在迭代中发出定期结果?

问题描述

我可能有这样的事情:

val found = source.toCharArray.foreach{ c =>
  // Process char c
  // Sometimes (e.g. on newline) I want to emit a result to be
  // captured in 'found'.  There may be 0 or more captured results.
}

这表明了我的意图。我想迭代一些东西的集合。每当需要时,我想“发出”要在发现中捕获的结果。这不是直接的 1 对 1 之类的地图。collect() 是一个“拉”,对集合应用部分函数。我想要一个“推送”行为,我访问所有内容,但在需要时推出一些内容。

是否有我缺少的模式或收集方法可以做到这一点?

标签: scala

解决方案


显然,你有一个Collection[Thing],并且你想通过为每个Collection[Event]发出一个来获得一个新的。也就是说,你想要一个函数Collection[Event]Thing

(Collection[Thing], Thing => Collection[Event]) => Collection[Event]

这正是这样flatMap做的。


您可以使用嵌套的 s 将其写下来,for其中第二个生成器定义了必须为来自源的每个输入“发出”哪些“事件”。例如:

val input = "a2ba4b"

val result = (for {
  c <- input
  emitted <- {
    if (c == 'a') List('A')
    else if (c.isDigit) List.fill(c.toString.toInt)('|')
    else Nil
  }
} yield emitted).mkString

println(result)

印刷

 A||A||||

因为每个'a'发出一个'A',每个数字发出正确数量的计数标记,并且所有其他符号都被忽略。


还有其他几种表达相同事物的方法,例如,上面的表达式也可以用显式flatMap和模式匹配来重写,而不是if-else

println(input.flatMap{
  case 'a' => "A"
  case d if d.isDigit => "|" * (d.toString.toInt)
  case _ => ""
})

推荐阅读