빈 Seq에 대한 Option [T]의 최소 / 최대?
저는 Seq[T]
"가장 작은"요소를 찾으려고하는 스칼라 체조를 약간하고 있습니다. 이것이 내가 지금하는 일입니다.
val leastOrNone = seq.reduceOption { (best, current) =>
if (current.something < best.something) current
else best
}
그것은 잘 작동하지만, 나는 그다지 만족스럽지 않습니다. 그런 단순한 일에는 조금 길고 "if"에 대해서는별로 신경 쓰지 않습니다 . 사용하면 minBy
훨씬 더 우아합니다.
val least = seq.minBy(_.something)
...하지만 min
및 minBy
던져 예외 순서가 비어있을 때. 빈 목록에서 가장 작은 요소를 찾는 관용적이고 우아한 방법이 Option
있습니까?
시작 Scala 2.13
, minByOption
/ maxByOption
는 이제 표준 라이브러리의 일부이며 None
시퀀스가 비어 있으면 반환 합니다.
seq.minByOption(_.something)
List((3, 'a'), (1, 'b'), (5, 'c')).minByOption(_._1) // Option[(Int, Char)] = Some((1,b))
List[(Int, Char)]().minByOption(_._1) // Option[(Int, Char)] = None
seq.reduceOption(_ min _)
당신이 원하는 것은 무엇입니까?
편집 : 다음은 다음을 통합하는 예입니다 _.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))
또는 일반적인 방법으로 :
def minOptionBy[A, B: Ordering](seq: Seq[A])(f: A => B) =
seq reduceOption Ordering.by(f).min
호출 할 수있는 minOptionBy(seq)(_.something)
O(n)
Scalaz를 사용 하는 안전하고 컴팩트 한 버전 :
xs.nonEmpty option xs.minBy(_.foo)
O(nlogn)
복잡성 으로 인해 더 큰 목록에 대한 옵션은 거의 없습니다 .
seq.sortBy(_.something).headOption
이건 어때요?
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)
.
이전에도 동일한 문제가 있으므로 Ordered를 확장하고 비교 기능을 구현합니다. 다음은 예입니다.
case class Point(longitude0: String, latitude0: String) extends Ordered [Point]{
def this(point: Point) = this(point.original_longitude,point.original_latitude)
val original_longitude = longitude0
val original_latitude = latitude0
val longitude = parseDouble(longitude0).get
val latitude = parseDouble(latitude0).get
override def toString: String = "longitude: " +original_longitude +", latitude: "+ original_latitude
def parseDouble(s: String): Option[Double] = try { Some(s.toDouble) } catch { case _ => None }
def distance(other: Point): Double =
sqrt(pow(longitude - other.longitude, 2) + pow(latitude - other.latitude, 2))
override def compare(that: Point): Int = {
if (longitude < that.longitude)
return -1
else if (longitude == that.longitude && latitude < that.latitude)
return -1
else
return 1
}
}
그래서 포인트의 seq가 있으면 최대 또는 최소 방법을 요청할 수 있습니다.
var points = Seq[Point]()
val maxPoint = points.max
val minPoint = points.min
항상 다음과 같이 할 수 있습니다.
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
Haskell에서는 다음 minimumBy
과 같이 호출을 래핑합니다.
least f x | Seq.null x = Nothing
| otherwise = Just (Seq.minimumBy f x)
참조 URL : https://stackoverflow.com/questions/10922237/min-max-with-optiont-for-possibly-empty-seq
'IT이야기' 카테고리의 다른 글
USB 드라이브가 연결되어 있는지 확인하는 방법 (0) | 2021.04.15 |
---|---|
libgmp-10.dll이 누락되었습니다. (0) | 2021.04.15 |
첫 번째 열이 문자열이고 나머지 열이 숫자 일 때 numpy.genfromtxt를 사용하는 방법은 무엇입니까? (0) | 2021.04.15 |
Passport.js 인증 실패시 JSON 응답을 다시 보내기 (0) | 2021.04.15 |
Spring @Value가 속성 파일의 값으로 확인되지 않을 경우 (0) | 2021.04.15 |