scala中每个组的最大值

scala中每个组的最大值,scala,sorting,grouping,Scala,Sorting,Grouping,我有一个id和分数数组,我想找到每个id的最高分数 val idAndScore = Array( ("10022 10021", -6.1825), ("10022 10021", -6.477912), ("10022 10021", -7.207875), ("10022 10021", -6.251606), ("10022 10021", -6.343815), ("10022 10021", -6.62864), ("29920

我有一个id和分数数组,我想找到每个id的最高分数

val idAndScore = Array(
    ("10022 10021", -6.1825),
    ("10022 10021", -6.477912),
    ("10022 10021", -7.207875),
    ("10022 10021", -6.251606),
    ("10022 10021", -6.343815),
    ("10022 10021", -6.62864),
    ("29920 29919", -9.134842),
    ("29920 29919", -9.049803),
    ("29920 29919", -9.658904),
    ("29920 29919", -9.186851),
    ("29920 29919", -8.525129),
    ("29920 29919", -9.46663),
    ("29920 29919", -8.496784),
    ("29920 29919", -9.2584),
    ("29946 29945", -10.010943),
    ("29946 29945", -8.588902),
    ("29946 29945", -8.915169),
    ("29946 29945", -8.538752)
)
所需的输出为fallows

(10022 10021,-6.1825)
(29920 29919,-8.496784)
(29946 29945,-8.538752)
val top = idAndScore.groupBy { case (id, score) => id }
.flatMap(_._2.toList.sortBy { case (id, score) => score }.reverse)
我试过了

val top = idAndScore.groupBy { case (id, score) => id }
.flatMap(_._2.toList.sortBy { case (id, score) => score })
但它给了我

(29946 29945,-8.538752)
(29920 29919,-8.496784)
(10022 10021,-6.1825)
并添加反向作为休耕

(10022 10021,-6.1825)
(29920 29919,-8.496784)
(29946 29945,-8.538752)
val top = idAndScore.groupBy { case (id, score) => id }
.flatMap(_._2.toList.sortBy { case (id, score) => score }.reverse)
给予

我已经能够通过使用sort两次和reverse获得所需的输出。但我认为这可能是一种更干净的方式。如有任何建议,将不胜感激

idAndScore.groupBy(_._1).mapValues(_.max).map(_._2).toList.sortBy(- _._2)


可能是更高效的版本,因为它只是维护max,而不是值列表,以便以后获取max

idAndScore.foldLeft(Map[String, Double]() withDefaultValue Double.MinValue)
                   { case (m, (k, v)) => m updated (k, v max m(k))}
          .toSeq
          .sortBy{-_._2}

// Seq[(String, Double)] = ArrayBuffer((10022 10021,-6.1825),
                                       (29920 29919,-8.496784),
                                       (29946 29945,-8.538752))

可能是更高效的版本,因为它只是维护max,而不是值列表,以便以后获取max

idAndScore.foldLeft(Map[String, Double]() withDefaultValue Double.MinValue)
                   { case (m, (k, v)) => m updated (k, v max m(k))}
          .toSeq
          .sortBy{-_._2}

// Seq[(String, Double)] = ArrayBuffer((10022 10021,-6.1825),
                                       (29920 29919,-8.496784),
                                       (29946 29945,-8.538752))

输入是否已按id排序?不,不是。抱歉,在本例中,它们看起来是这样的。使用
reduceByKey
而不是
groupByKey
可以加快速度。正如
groupByKey
的文档所说,“注意:此操作可能非常昂贵。如果您分组是为了对每个键执行聚合(例如求和或平均),则使用pairddfunctions.aggregateByKey或pairddfunctions.reduceByKey将提供更好的性能。”@感谢ArchetyPalpaul,但在这种情况下,我们不执行并行spark rdd操作。这是串行scala。@user3771345,啊,好的!通常情况下,问题恰恰相反——人们发布的问题看起来像数组问题,但实际上他们使用的是Spark。但是,只跟踪最大值的折叠可能仍然比groupBy快,因为它为每个键建立了一个列表,其中您只对最大值感兴趣……输入是否已按id排序?不,不是。抱歉,在本例中,它们看起来是这样的。使用
reduceByKey
而不是
groupByKey
可以加快速度。正如
groupByKey
的文档所说,“注意:此操作可能非常昂贵。如果您分组是为了对每个键执行聚合(例如求和或平均),则使用pairddfunctions.aggregateByKey或pairddfunctions.reduceByKey将提供更好的性能。”@感谢ArchetyPalpaul,但在这种情况下,我们不执行并行spark rdd操作。这是串行scala。@user3771345,啊,好的!通常情况下,问题恰恰相反——人们发布的问题看起来像数组问题,但实际上他们使用的是Spark。然而,只跟踪最大值的折叠可能仍然比groupBy快,因为它为每个关键点建立了一个列表,其中您只对最大值感兴趣……很好,这很有效。你能解释一下吗。对我来说,你似乎是在乘以-。@user3771345我们需要按数值排序,这样我们就可以对它们求反,以获得所需的顺序,我也更新了我的答案,嗯。很好,这很有效。你能解释一下吗。对我来说,你似乎是在乘以-。@user3771345我们需要按数值排序,这样我们就可以对它们求反,以获得所需的顺序,我也更新了我的答案,HTH。