如何一次“查找”序列元素和谓词结果?

时间:2011-12-03 09:33:21

标签: scala find scala-collections

假设我有一个函数f(n:Int):Option[String]。我想找到1 <= k <= 10不是f(k)的{​​{1}}这样的None。我可以按如下方式编写代码:

(1 to 10).find(k => f(k).isDefined)

现在我想知道 kf(k)

val k = (1 to 10).find(f(_).isDefined)
val s = f(k)

不幸的是,此代码会两次调用f(k)。您如何一次找到kf(k)

3 个答案:

答案 0 :(得分:9)

我的第一次尝试是:

(1 to 10).view map {k => (k, f(k))} find {_._2.isDefined}

使用view可避免创建中间map。或者更好的模式匹配和部分功能:

(1 to 10).view map {k => (k, f(k))} collectFirst {case (k, Some(v)) => (k, v)}

如果找不到满足Option[(Int, java.lang.String)]的元素,则返回Nonef。)

您也可以尝试使用.zipWithIndex

答案 1 :(得分:2)

稍短一些 - 只需映射并找到:

// for testing
def f (n: Int): Option [String] = 
  if (n > 0) Some ((List.fill (n) ("" + n)).mkString) else None

(-5 to 5).map (i => (i, f(i))).find (e => e._2 != None) 

// result in REPL
res67: Option[(Int, Option[String])] = Some((1,Some(1)))

答案 2 :(得分:2)

Tomasz Nurkiewicz解决方案稍微冗长的版本:

xs = (1 to 10).view      
xs zip { xs map { f(_) } } collectFirst { case (k, Some(v)) => (k, v) }