scalaz.Foldable有一个maximumBy方法,它在容器中找到一个最大元素。但是否有一种优雅的方法可以找到所有使用黄玉的人?ie:
Vector(Person("Ben", 1), Person("Jil", 3), Person("Bob", 3)).maximumsBy(_.age)
== Vector(Person("Jil", 3), Person("Bob", 3))我有一个问题,如果有几个相等的最大值,我想从这些候选人中随机选择。
发布于 2015-03-27 04:03:10
你可以做这样的事
implicit def MaxNonEmptyListSemigroup[A : Order]:
Semigroup[NonEmptyList[A]] = new Semigroup[NonEmptyList[A]] {
def append(l1: NonEmptyList[A], l2: =>NonEmptyList[A]): NonEmptyList[A] =
Order[A].apply(l1.head, l2.head) match {
case GT => l1
case LT => l2
case EQ => l1 append l2
}
}
// returns None if the list is empty
// otherwise returns Some(non-empty-list of maximum elements)
list.foldMap1Opt(a => NonEmptyList.nels(a)) :: Option[NonEmptyList[A]]发布于 2015-03-27 22:03:59
理想情况下,maximumsBy将返回与所提供的容器类型相同的最大值。要有效地做到这一点,似乎需要scalaz.Reducer,一种将模型附加到容器中并将其添加到容器中的类型类型。
import scalaz._
import Ordering._
import std.AllInstances._
object Maximums extends App {
def maximumsBy[F[_]: Foldable, A, B: Order](fa: F[A])(f: A => B)
(implicit r: Reducer[A, F[A]]): Option[F[A]] =
Foldable[F].foldMapLeft1Opt(fa)(a => (f(a), r.unit(a))) {
case (curr@(max, maxes), a) => {
val next = f(a)
Order[B].apply(next, max) match {
case GT => (next, r.unit(a))
case LT => curr
case EQ => (max, r.snoc(maxes, a))
}
}
}.map(_._2)
println(maximumsBy(Vector(("a", 1), ("c", 3), ("c", 3)))(_._2))
println(maximumsBy(List(("a", 1), ("c", 3), ("c", 3)))(_._2))
//Output:
//Some(Vector((c,3), (c,3)))
//Some(List((c,3), (c,3)))
}我对maximumsBy的结果是多么的复杂感到有些沮丧。有什么方法可以在保持相同行为的同时简化它呢?
https://stackoverflow.com/questions/29292699
复制相似问题