2

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

  1. 一些
  2. 并且满足一个谓词

最好的惯用方法是什么?

另外:如果在此过程中抛出异常,我想忽略它并继续下一个成员

4

4 回答 4

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

至于忽略异常……是谓词 that couldthrow吗?因为那不是很明智。尽管如此……</p>

optionIterator find {
  case Some(x) => Try(predicate(x)) getOrElse false
  case _       => false
}
于 2014-05-08T02:43:51.733 回答
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)

得到第一个超过五的偶数不会破坏测试。

于 2014-05-08T05:11:42.563 回答
1

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

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

flatMap获取一个集合的集合(其中一个可迭代的集合Option被认为是最大大小为 1 的集合)并将其转换为单个集合:OptionEither

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返回迭代中与谓词匹配的第一个条目,Option或者None如果没有匹配项:

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

scala> (1 to 10).find(_ == 11)
res1: Option[Int] = None
于 2014-05-08T02:25:45.063 回答
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将产生一个定义值的 Seq,所有的 None 都将被丢弃

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

然后在序列上使用find - 您将获得满足谓词的第一个值。请注意,找到的值被包装为选项,导致find在“未找到”的情况下应该能够返回有效值(无)值。

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

据我所知,这对 Scala 来说是“OK”的方式。

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

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

注意这里我们有 Some(Some(-7)) 因为collectFind应该有机会产生“未找到”的值,所以这里 1st Some - 来自 collectFirst,2nd Some - 来自 Option 的 Seq 的源元素。

如果您需要手中的值,可以将 Some(Some(-7))展平。

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

如果什么也没找到 - 你将拥有 None

scala> l.collectFirst({ case a@Some(x) if x < -10 => a }).flatten
res9: Option[Int] = None
于 2014-05-08T17:04:45.843 回答