Scala成语首先从迭代器中找到一些Option

时间:2014-05-08 02:02:10

标签: scala scala-collections scala-option

我有一个选项迭代器,想找到第一个成员:

  1. 一些
  2. 并符合谓词
  3. 最好的惯用方法是什么?

    另外:如果一路上抛出异常,我想忽略它并转移到下一个成员

4 个答案:

答案 0 :(得分:6)

optionIterator find { case Some(x) if predicate(x) => true  case _ => false }

至于忽略异常......这是谓词throw吗?因为这不是真的明智。尽管如此...

optionIterator find {
  case Some(x) => Try(predicate(x)) getOrElse false
  case _       => false
}

答案 1 :(得分:3)

为油漆工作添加最佳和惯用的外套:

scala> val vs = (0 to 10) map { case 3 => None case i => Some(i) }
vs: scala.collection.immutable.IndexedSeq[Option[Int]] = Vector(Some(0), Some(1), Some(2), None, Some(4), Some(5), Some(6), Some(7), Some(8), Some(9), Some(10))

scala> def p(i: Int) = if (i % 2 == 0) i > 5 else ???
p: (i: Int)Boolean

scala> import util._
import util._

scala> val it = vs.iterator
it: Iterator[Option[Int]] = non-empty iterator

scala> it collectFirst { case Some(i) if Try(p(i)) getOrElse false => i }
res2: Option[Int] = Some(6)

获得超过5的第一个偶数而且不会爆炸测试。

答案 2 :(得分:1)

假设您可以包装谓词,以便任何错误返回false:

iterator.flatMap(x => x).find(yourSafePredicate)

flatMap收集集合(其中Option的可迭代为OptionEither被视为最大为1的集合)并将其转换为一个集合:

scala> for { x <- 1 to 3; y <- 1 to x } yield x :: y :: Nil
res30: IndexedSeq[List[Int]] = Vector(List(1, 1), List(2, 1), List(2, 2), List(3, 1), List(3, 2), List(3, 3))

scala> res30.flatMap(x => x)
res31: IndexedSeq[Int] = Vector(1, 1, 2, 1, 2, 2, 3, 1, 3, 2, 3, 3)

find会返回您的iterable中的第一个条目,如果没有匹配项,则会将谓词与OptionNone匹配:

scala> (1 to 10).find(_ > 3)
res0: Option[Int] = Some(4)

scala> (1 to 10).find(_ == 11)
res1: Option[Int] = None

答案 3 :(得分:1)

一些示例数据

scala> val l = Seq(Some(1),None,Some(-7),Some(8))
l: Seq[Option[Int]] = List(Some(1), None, Some(-7), Some(8))

在Seq of Options上使用 flatMap 将生成一个已定义值的序列,所有无效将被丢弃

scala> l.flatMap(a => a)
res0: Seq[Int] = List(1, -7, 8)

然后在序列上使用 find - 您将获得满足谓词的第一个值。注意,找到的值被包装为Option,因为 find 应该能够在&#34; not found&#34;的情况下返回有效值(None)值。情况。

scala> l.flatMap(a => a).find(_ < 0)
res1: Option[Int] = Some(-7)

据我所知,它是&#34;好的&#34;斯卡拉的方式。

可能更习惯的方法是在Seq上使用收集 / collectFirst ...

scala> l.collectFirst { case a@Some(x) if x < 0 => a }
res2: Option[Some[Int]] = Some(Some(-7))

注意这里我们有一些(一些(-7)),因为 collectFind 应该有机会产生&#34;未找到&#34;价值,所以这里第一部分 - 来自collectFirst,第二部分 - 来自期权的Seq的源元素。

如果您需要手中的值,可以展平某些(有些(-7))。

scala> l.collectFirst({ case a@Some(x) if x < 0 => a }).flatten
res3: Option[Int] = Some(-7)

如果找不到任何内容 - 您将拥有无

scala> l.collectFirst({ case a@Some(x) if x < -10 => a }).flatten
res9: Option[Int] = None