63

私はSeq[T]、「最小の」要素を見つけようとする Scala 体操を少ししています。これは私が今していることです:

val leastOrNone = seq.reduceOption { (best, current) =>
    if (current.something < best.something) current
    else best
}

これは問題なく動作しますが、私は満足していません。このような単純なことには少し長く、「if」はあまり気にしません。を使用minByすると、はるかにエレガントになります。

val least = seq.minBy(_.something)

...しかし、シーケンスが空の場合は例外minminByスローします。おそらく空のリストの最小要素を として見つける慣用的でよりエレガントな方法はありOptionますか?

4

10 に答える 10

8

Scalaz を使用した安全でコンパクトなO(n)バージョン:

xs.nonEmpty option xs.minBy(_.foo)
于 2015-02-24T08:01:03.007 に答える
5

O(nlogn)複雑なため、より大きなリストのオプションはほとんどありません。

seq.sortBy(_.something).headOption
于 2012-06-06T21:27:28.213 に答える
1

これはどう?

import util.control.Exception._
allCatch opt seq.minBy(_.something)

または、他の例外を飲み込みたくない場合は、より詳細に:

catching(classOf[UnsupportedOperationException]) opt seq.minBy(_.something)

または、次のような方法ですべてのコレクションをポンピングできます。

import collection._

class TraversableOnceExt[CC, A](coll: CC, asTraversable: CC => TraversableOnce[A]) {

  def minOption(implicit cmp: Ordering[A]): Option[A] = {
    val trav = asTraversable(coll)
    if (trav.isEmpty) None
    else Some(trav.min)
  }

  def minOptionBy[B](f: A => B)(implicit cmp: Ordering[B]): Option[A] = {
    val trav = asTraversable(coll)
    if (trav.isEmpty) None
    else Some(trav.minBy(f))
  }
}

implicit def extendTraversable[A, C[A] <: TraversableOnce[A]](coll: C[A]): TraversableOnceExt[C[A], A] =
  new TraversableOnceExt[C[A], A](coll, identity)

implicit def extendStringTraversable(string: String): TraversableOnceExt[String, Char] =
  new TraversableOnceExt[String, Char](string, implicitly)

implicit def extendArrayTraversable[A](array: Array[A]): TraversableOnceExt[Array[A], A] =
  new TraversableOnceExt[Array[A], A](array, implicitly)

そして、書くだけseq.minOptionBy(_.something)です。

于 2012-06-06T21:18:07.120 に答える
1

あなたはいつでも次のようなことをすることができます:

case class Foo(num: Int)

val foos: Seq[Foo] = Seq(Foo(1), Foo(2), Foo(3))
val noFoos: Seq[Foo] = Seq.empty

def minByOpt(foos: Seq[Foo]): Option[Foo] =
  foos.foldLeft(None: Option[Foo]) { (acc, elem) => 
    Option((elem +: acc.toSeq).minBy(_.num)) 
  }

次に、次のように使用します。

scala> minByOpt(foos)
res0: Option[Foo] = Some(Foo(1))

scala> minByOpt(noFoos)
res1: Option[Foo] = None
于 2018-11-28T03:45:13.567 に答える
-4

minimumByHaskell では、呼び出しを次のようにラップします。

least f x | Seq.null x = Nothing
          | otherwise  = Just (Seq.minimumBy f x) 
于 2012-06-06T21:07:00.203 に答える