如何在列表中查找匹配元素并将其作为Scala API方法映射?

时间:2011-03-29 21:34:59

标签: scala scala-2.8

有没有一种方法可以在不同时执行以下两种方法的情况下执行以下操作:findmap

val l = 0 to 3
l.find(_ * 33 % 2 == 0).map(_ * 33) // returns Some(66)

4 个答案:

答案 0 :(得分:27)

如何使用收藏?

// Returns List(66)
List(1, 2, 3) collect { case i if (i * 33 % 2 == 0) => i * 33 }

然而,这将返回所有匹配,而不仅仅是第一个匹配。

基于Scala 2.9,答案会更好:

// Returns Some(66)
List(1, 2, 3) collectFirst { case i if (i * 33 % 2 == 0) => i * 33 }

在评论中建议添加head以获得Scala 2.8版本的解决方案并不是非常有效,我担心。也许在那种情况下我会坚持你自己的代码。在任何情况下,为了确保它返回一个选项,您不应该致电head,而是headOption

// Returns Some(66)
List(1, 2, 3) collect { case i if (i * 33 % 2 == 0) => i * 33 } headOption

答案 1 :(得分:18)

如果您不想多次执行map()操作(例如,如果这是一次昂贵的数据库查询),您可以这样做:

l.view.map(_ * 33).find(_ % 2 == 0)

view使得集合变得懒惰,因此map()操作的数量最小化。

答案 2 :(得分:6)

嘿,看,这又是我的小伙伴findMap了!

/**
 * Finds the first element in the list that satisfies the partial function, then 
 * maps it through the function.
 */
def findMap[A,B](in: Traversable[A])(f: PartialFunction[A,B]): Option[B] = {
  in.find(f.isDefinedAt(_)).map(f(_))
}

请注意,与接受的答案不同,但与其中一条评论中提到的collectFirst方法不同,这个人一找到匹配的元素就会停止。

答案 3 :(得分:-1)

这可以做到,但如果你说出你真正想要实现的目标会更容易:

l.flatMap(n => if (n * 33 % 2 == 0) Some(n * 33) else None).headOption