跟进这个问题,我不知道为什么 maxBy的Traversable[T]返回一个值T,而不是一个序列T(列表或类似).这看起来很常见.例如(来自上一个问题):
有关成绩的学生名单
List(Student("Mike", "A"), Student("Pete", "B"), Student("Paul", A))"
我想得到
List(Student("Mike", "A"), Student("Paul", A))
有没有人知道任何标准实现maxBy,它返回一系列找到的项目?
没有单一的命令.我所知道的最短 - 将所有东西分组,而不仅仅是作为中间体的最大值 -
xs.groupBy(f).maxBy(_._1)._2
Run Code Online (Sandbox Code Playgroud)
为了提高效率,折叠是用于查找总和和最大值以及各种类似事物的通用工具.基本上,任何时候你需要在积累一些答案时跑过你的收藏,使用折叠.在这种情况下,
(xs.head /: xs.tail) {
(biggest, next) => if (f(biggest) < f(next)) next else biggest
}
Run Code Online (Sandbox Code Playgroud)
maxBy(f)如果您不介意为每个元素重新评估该函数两次,则会执行
((xs.head, f(xs.head)) /: xs.tail) {
case (scored, next) =>
val nextscore = f(next)
if (scored._2 < nextscore) (next, nextscore)
else scored
}._1
Run Code Online (Sandbox Code Playgroud)
将每个元素只进行一次评估.如果要保留序列,可以将其修改为
(Seq(xs.head) /: xs.tail) {
(bigs, next) =>
if (f(bigs.head) > f(next)) bigs
else if (f(bigs.head) < f(next)) Seq(next)
else bigs :+ next
}
Run Code Online (Sandbox Code Playgroud)
保留列表(相应的单一评估表格留给读者练习).
最后,即使是接近最大效率的版本是不是所有这很难管理,如果你愿意使用一些可变的变量(希望精心隐藏在一个代码块像我这里)
val result = {
var bigs = xs.take(0).toList
var bestSoFar = f(xs.head)
xs.foreach{ x =>
if (bigs.isEmpty) bigs = x :: bigs
else {
val fx = f(x)
if (fx > bestSoFar) {
bestSoFar = fx
bigs = List(x)
}
else if (fx == bestSoFar) bigs = x :: bigs
}
}
bigs
}
Run Code Online (Sandbox Code Playgroud)
(这将以相反的顺序返回,顺便说一下).
| 归档时间: |
|
| 查看次数: |
6018 次 |
| 最近记录: |