最小/最大,选项[T]可能为空Seq?

gus*_*afc 54 scala scala-collections

我正在做一些Scala体操,Seq[T]在那里我尝试找到"最小"的元素.这就是我现在所做的:

val leastOrNone = seq.reduceOption { (best, current) =>
    if (current.something < best.something) current
    else best
}
Run Code Online (Sandbox Code Playgroud)

它工作正常,但我不太满意 - 对于这么简单的事情来说有点长,而且我并不关心"如果".使用minBy会更优雅:

val least = seq.minBy(_.something)
Run Code Online (Sandbox Code Playgroud)

......但minminBy抛出异常时序列为空.是否有一种惯用的,更优雅的方式来查找可能为空的列表中的最小元素Option

Lui*_*hys 70

seq.reduceOption(_ min _)
Run Code Online (Sandbox Code Playgroud)

做你想要的?


编辑:以下是一个结合您的示例_.something:

case class Foo(a: Int, b: Int)
val seq = Seq(Foo(1,1),Foo(2,0),Foo(0,3))
val ord = Ordering.by((_: Foo).b)
seq.reduceOption(ord.min)  //Option[Foo] = Some(Foo(2,0))
Run Code Online (Sandbox Code Playgroud)

或者,作为通用方法:

def minOptionBy[A, B: Ordering](seq: Seq[A])(f: A => B) = 
  seq reduceOption Ordering.by(f).min
Run Code Online (Sandbox Code Playgroud)

你可以调用它 minOptionBy(seq)(_.something)

  • 也可以使用`seq reduceOption math.min`.这样更有效,因为它不需要隐式转换. (2认同)

Xav*_*hot 19

启动Scala 2.13,minByOption/ maxByOption现在是标准库的一部分,None如果序列为空则返回:

seq.minByOption(_.something)
Run Code Online (Sandbox Code Playgroud)
List((3, 'a'), (1, 'b'), (5, 'c')).minByOption(_._1) // Option[(Int, Char)] = Some((1,b))
List[(Int, Char)]().minByOption(_._1)                // Option[(Int, Char)] = None
Run Code Online (Sandbox Code Playgroud)


Eri*_*lun 8

O(n)Scalaz的安全,紧凑和版本:

xs.nonEmpty option xs.minBy(_.foo)
Run Code Online (Sandbox Code Playgroud)


Tom*_*icz 5

由于O(nlogn)复杂性,几乎没有选择任何更大的列表:

seq.sortBy(_.something).headOption
Run Code Online (Sandbox Code Playgroud)

  • @EricAllik 嗯。不知道我为什么这么写。几年前我显然不知道奥卡姆剃刀实际上是什么。可耻!现在我更欣赏这样的答案,尽管公认的答案是一个更好的主意。 (6认同)
  • @fatuhoku 从数学(因此是纯 FP?)的角度来看,`sortBy` + `headOption` 似乎等同于 `minByOpt` - 为什么它打破了奥卡姆剃刀? (3认同)

Ana*_*nov 5

Also, it is available to do like that

Some(seq).filter(_.nonEmpty).map(_.minBy(_.something))
Run Code Online (Sandbox Code Playgroud)