如何简洁地缩小下面的列表
Seq[Temp] = List(Temp(a,1), Temp(a,2), Temp(b,1))
到
List(Temp(a,2), Temp(b,1))
仅保留具有唯一第一个参数的Temp对象和第二个参数的最大值。
我的解决方案是使用很多groupBys,并且减少了很长的答案。
答案 0 :(得分:1)
你必须
groupBy
sortBy
值last
最大的示例,
scala> final case class Temp (a: String, value: Int)
defined class Temp
scala> val data : Seq[Temp] = List(Temp("a",1), Temp("a",2), Temp("b",1))
data: Seq[Temp] = List(Temp(a,1), Temp(a,2), Temp(b,1))
scala> data.groupBy(_.a).map { case (k, group) => group.sortBy(_.value).last }
res0: scala.collection.immutable.Iterable[Temp] = List(Temp(b,1), Temp(a,2))
或代替sortBy(fn).last
您可以maxBy(fn)
scala> data.groupBy(_.a).map { case (k, group) => group.maxBy(_.value) }
res1: scala.collection.immutable.Iterable[Temp] = List(Temp(b,1), Temp(a,2))
答案 1 :(得分:1)
您可以使用groupBy
生成max
,计算mapValues
中的Temp
并将其转换回case class Temp(id: String, value: Int)
List(Temp("a", 1), Temp("a", 2), Temp("b", 1)).
groupBy(_.id).mapValues( _.map(_.value).max ).
map{ case (k, v) => Temp(k, v) }
// res1: scala.collection.immutable.Iterable[Temp] = List(Temp(b,1), Temp(a,2))
类,如下例所示:
maxBy
值得注意的是,在另一个答案中使用{{1}}的解决方案更有效,因为它最大限度地减少了必要的转换。
答案 2 :(得分:0)
您可以使用foldLeft
:
data.foldLeft(Map[String, Int]().withDefaultValue(0))((map, tmp) => {
map.updated(tmp.id, max(map(tmp.id), tmp.value))
}).map{case (i,v) => Temp(i, v)}
这基本上是将groupBy
的逻辑与max
操作结合在一起。
注意这可能效率较低,因为groupBy
在内部使用mutable.Map
可避免不断重新创建新地图。如果您关心性能并准备使用可变数据,这是另一种选择:
val tmpMap = mutable.Map[String, Int]().withDefaultValue(0)
data.foreach(tmp => tmpMap(tmp.id) = max(tmp.value, tmpMap(tmp.id)))
tmpMap.map{case (i,v) => Temp(i, v)}.toList
如果您需要保留数据订单,请使用ListMap
,如果需要特定订购,请使用最后排序。