按值减少scala中的列表

时间:2018-06-01 00:23:04

标签: scala reduce

如何简洁地缩小下面的列表

Seq[Temp] = List(Temp(a,1), Temp(a,2), Temp(b,1))

List(Temp(a,2), Temp(b,1))

仅保留具有唯一第一个参数的Temp对象和第二个参数的最大值。

我的解决方案是使用很多groupBys,并且减少了很长的答案。

3 个答案:

答案 0 :(得分:1)

你必须

  • groupBy
  • ASC订单中的
  • 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,如果需要特定订购,请使用最后排序。