l.find{x => x.p1 == x.p2}.getOrElse(l.maxBy(_.p2))
更新:在您更新的问题中,您说“给我 p2 最大的项目,如果找不到,请给我最低 p1 等等”。但是根据定义,总是有一个最大值(除非列表为空,但我认为列表不能为空)。所以这实际上只是“给我最大 p2 的项目”(因此上述解决方案)。
更新 2:所以问题又变了,现在是“找到 p1 == p2 的项目,如果找不到,请给我 p2 > p1 的项目,如果找不到,请给 p1 =方(p2)等等”。我想你毕竟真的需要一个通用的解决方案。所以这是我的看法:
// The list of predicates, in order of priority
// (you can add/remove predicates as you see fit)
val predicates = List[A => Boolean](
x => x.p1 == x.p2,
x => x.p2 > x.p1,
x => x.p1 == x.p2*x.p2
)
val indexedPredicates = predicates.reverse.zipWithIndex
def score( x: A ): Option[Int] = indexedPredicates.find(_._1(x)).map(_._2)
def priorityFind( l: List[A] ): A = l.maxBy(score)
这个想法是你为每个元素赋予一个分数:如果元素不匹配任何谓词,则为 None,如果它匹配最后一个谓词,则 Some(0),如果它匹配最后一个但一个谓词,则 Some(1),依此类推。然后你只取得分最高的那个(None
比任何Some
实例都“小”,所以这与我们想要的一致)。
如果你想正确处理没有元素匹配任何谓词的情况,你可以这样改变priorityFind
:
def priorityFind( l: List[A] ): Option[A] = {
val filtered = l.view.flatMap{x => score(x).map(x -> _) }
if ( filtered.isEmpty ) None
else Some( filtered.maxBy(_._2)._1 )
}