英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论