将一个地图转换成一个新地图,并处理可能重复的新键,在Scala中。

huangapple go评论49阅读模式
英文:

How to convert a map to a new map and handle possible duplicated new key in scala

问题

I understand your request, and here is the translated code part:

我想将一个映射转换为一个新映射新映射的新键将由旧键生成但新键可能重复因此我需要对相同的新键进行结果汇总

例如`val oldMap = Map(2 -> 111, 3 -> 222, 4 -> 333)`

新键将由某个函数生成例如 **k => k % 2**因此新键将为 **0****1**对于相同的新键我想要汇总结果或传递一些聚合函数

结果新映射`Map(0 -> 444, 1 -> 222)`

我尝试过 `oldMap.groupBy( k => k._1 % 2)`但结果是 `Map(0 -> Map(2 -> 111, 4 -> 333), 1 -> Map(3 -> 222))`值部分是旧映射的一部分而且我不知道如何传递聚合函数

Please note that the translated code retains the original formatting and structure.

英文:

I would like to convert a map to a new map, the new key of the new map will be generated by the old key, but the new key could be duplicated, so I need to aggregate results for the same new key.

for example: val oldMap = Map(2 -> 111, 3 -> 222, 4 -> 333)

the new key will be generated by some function, e.g. k => k % 2. Therefore, the new key will be, 0 and 1. And for the same new key, I want to sum up the result (or pass some aggregation function)

Result new map: Map(0 -> 444, 1 -> 222)

I tried oldMap.groupBy( k => k._1 % 2) but the result is Map(0 -> Map(2 -> 111, 4 -> 333), 1 -> Map(3 -> 222)), the value is part of the old map. And I don't know how to pass an aggregate function.

答案1

得分: 3

groupMapReduce是在您使用Scala 2.13或更高版本时非常方便的工具:

oldMap.groupMapReduce(_._1 % 2)(_._2)(_ + _)

第一个参数与groupBy相同。第二个参数表示只保留值,第三个参数对每个组中的所有值求和。

英文:

groupMapReduce is pretty handy for this situation if you have Scala 2.13 or later:

oldMap.groupMapReduce(_._1 % 2)(_._2)(_ + _)

The first argument is the same as groupBy. The second argument says just keep the value, and the third argument sums all the values in each group.

答案2

得分: 2

val oldMap = Map(2 -> 111, 3 -> 222, 4 -> 333)
val newMap = oldMap.groupBy { case (k, v) => k % 2 } 
                  .view
                  .mapValues(_.values.sum) 
                  .toMap // if we need convert to strict Map.

You can use the 'groupBy' method to group the entries and then use 'mapValues' for aggregation. You can replace the '_.values.sum' function with any other aggregation function.

Edit: As mentioned by @Dmytro Mitin, we can use 'view' to create a lazy view of the original map, and then use 'mapValues'. Use of '.view' enables us to use 'mapValues' without converting it to a collection. Once all these aggregation operations are done, we can use 'toMap' and get the map back.

英文:
val oldMap = Map(2 -> 111, 3 -> 222, 4 -> 333)
val newMap = oldMap.groupBy { case (k, v) => k % 2 } 
                  .view
                  .mapValues(_.values.sum) 
                  .toMap // if we need convert to strict Map. 

You can use the 'groupBy' mehod to group the entries and then use 'mapValues' for aggrigation. You can replace the '_.values.sum' function with any other aggregation function.

Edit: As mentioned by @Dmytro Mitin, we can use view to create a lazy view of the original map, and then use mapValues
Use of .view enables us to use mapValues without converting it to collection. Once all these aggregation operations are done, we can use toMap and get the map back

答案3

得分: 1

(基于 @LuisMiguelMejíaSuárez 的评论)

你也可以使用 Cats


oldMap.groupBy(_._1 % 2).view.mapValues(_.toList.foldMap(_._2)).toMap

或者

import cats.syntax.foldable._
import alleycats.std.map._

oldMap.groupBy(_._1 % 2).view.mapValues(Foldable[Map[Int, *]].fold(_)).toMap
英文:

(Based on @LuisMiguelMejíaSuárez's comment)

You can use Cats as well

import cats.syntax.foldable._

oldMap.groupBy(_._1 % 2).view.mapValues(_.toList.foldMap(_._2)).toMap

or

import cats.Foldable
import cats.syntax.foldable._
import alleycats.std.map._

oldMap.groupBy(_._1 % 2).view.mapValues(Foldable[Map[Int, *]].fold(_)).toMap

huangapple
  • 本文由 发表于 2023年4月17日 01:53:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76029446.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定