在 Scala 中查找集合中的第一个定义项
Find the first defined item in a collection in Scala
给定一个集合 coll: C[A]
和一个函数 f: A => Option[B]
,Scala 中获取 coll
中第一项的惯用方法是什么,其中 f
没有定义评估整个系列?
这是我想要的签名:
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B]
像 coll.flatMap(f).headOption
这样天真的方法会评估整个集合。我们可以做 coll.view.flatMap(f).headOption
或 coll.collectFirst(Function.unlift(f))
但是在标准库或函数式编程文献或 scalaz/cats 中是否还有其他东西可以让我这样做?
使用 find(p: A => Boolean)
怎么样?
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] =
coll.find(f(_).isDefined).flatMap(f(_))
这需要两次调用 f.apply()
,但只会调用 apply()
,直到找到返回已定义选项的第一个元素。
编辑:考虑一下(但 Victor 抢在我之前),collectFirst()
也是一个更优雅的选择:
coll.collectFirst(Function.unlift(f))
IMO coll.collectFirst(Function.unlift(f))
如果您想使用标准的东西,这看起来是一个不错的解决方案。但是使用递归很容易实现:
@annotation.tailrec
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] =
if (coll.isEmpty) None
else {
val r = f(coll.head)
if (r.isEmpty) findFirstDefined(coll.tail)(f)
else r
}
如问题中所述,这似乎是一个不错的解决方案:
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] =
coll.collectFirst(Function.unlift(f))
给定一个集合 coll: C[A]
和一个函数 f: A => Option[B]
,Scala 中获取 coll
中第一项的惯用方法是什么,其中 f
没有定义评估整个系列?
这是我想要的签名:
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B]
像 coll.flatMap(f).headOption
这样天真的方法会评估整个集合。我们可以做 coll.view.flatMap(f).headOption
或 coll.collectFirst(Function.unlift(f))
但是在标准库或函数式编程文献或 scalaz/cats 中是否还有其他东西可以让我这样做?
使用 find(p: A => Boolean)
怎么样?
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] =
coll.find(f(_).isDefined).flatMap(f(_))
这需要两次调用 f.apply()
,但只会调用 apply()
,直到找到返回已定义选项的第一个元素。
编辑:考虑一下(但 Victor 抢在我之前),collectFirst()
也是一个更优雅的选择:
coll.collectFirst(Function.unlift(f))
IMO coll.collectFirst(Function.unlift(f))
如果您想使用标准的东西,这看起来是一个不错的解决方案。但是使用递归很容易实现:
@annotation.tailrec
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] =
if (coll.isEmpty) None
else {
val r = f(coll.head)
if (r.isEmpty) findFirstDefined(coll.tail)(f)
else r
}
如问题中所述,这似乎是一个不错的解决方案:
def findFirstDefined[A, B](coll: Traversable[A])(f: A => Option[B]): Option[B] =
coll.collectFirst(Function.unlift(f))