我有一个Map[String,Double]的列表,我想将它们的内容合并到一个Map[String,Double]中。我该如何用一种习惯的方式来做这件事呢?我想我应该可以用折叠来做这件事。例如:
val newMap = Map[String, Double]() /: listOfMaps { (accumulator, m) => ... }
此外,我想以一种通用的方式处理密钥冲突。也就是说,如果我向Map添加一个已经存在的键,我应该能够指定一个返回Double(在本例中)的函数,并接受该键的现有值,加上我试图添加的值。如果键还不存在于Map中,那么只需添加它,并且其值不变。
在我的特定情况下,我想构建一个Map[String,Double],这样如果map已经包含一个键,那么Double将被添加到现有的map值中。
我在我的特定代码中使用可变Map,但如果可能的话,我对更通用的解决方案感兴趣。
9条答案
按热度按时间0s0u357o1#
你可以这样做:
除了碰撞的特殊要求。
既然你确实有这个特殊的要求,也许最好的方法是这样做(2.8):
然后,您可以通过Pimp My Library模式将此方法添加到map类,并在原始示例中使用它而不是“
++
“:虽然这是在Python 2.8中写的,所以对于Python 2.7,
keysIterator
变成了keys
,filterKeys
可能需要用filter
和map
来写,&
变成了**
,等等,它不应该有太大的不同。ygya80vv2#
这个怎么样:
它在2.7.5和2.8.0中都可以工作。
czq61nw13#
我很惊讶还没有人想出这个解决方案:
完全满足您的需求:
1.将列表合并为单个Map
1.清除任何重复的密钥
范例:
flatten
将Map列表转换为元组的平面列表,toMap
将元组列表转换为删除了所有重复键的Mapjucafojl4#
从
Scala 2.13
开始,另一个解决方案是处理重复键,并且只基于标准库,包括在应用新的groupMapReduce操作符之前将Map
s合并为序列(flatten
),该操作符(顾名思义)相当于groupBy
,然后是Map和分组值的减少步骤:这是:
flatten
s(连接)Map为元组序列(List(("hello", 1.1), ("world", 2.2), ("goodbye", 3.3), ("hello", 4.4))
),保留所有键/值(甚至是重复键)group
s个元素基于它们的第一个元组部分(_._1
)(groupMapReduce的group部分)map
s分组的值到它们的第二个元组部分(_._2
)(map part of groupMapReduce)reduce
s通过求和来Map分组值(_+_
)(但它可以是任何reduce: (T, T) => T
函数)(reduce groupMap的一部分Reduce)groupMapReduce
步骤可以看作是相当于以下步骤的一次通过版本:nkoocmlb5#
有趣的是,我在这方面做了一点,我得到了以下内容(在2.7.5):
一般Map:
但是,伙计,这是可怕的投影和强迫和toList和诸如此类的。单独提问:有什么更好的方法来解决这个问题呢
对于可变Map,这是我在代码中处理的,并且使用不太通用的解决方案,我得到了这个:
这看起来更干净一点,但只适用于编写的可变Map。有趣的是,我第一次尝试上面(在我问问题之前)使用/:而不是foldLeft,但我得到了类型错误。我想/:和foldLeft基本上是等价的,但是编译器一直抱怨我需要(m,s)的显式类型。这是怎么回事
nfzehxib6#
我阅读这个问题很快,所以我不确定我是否错过了什么(比如它必须适用于2.7.x或没有scalaz):
您可以更改Double的monoid定义,并获得另一种方法来累积值,这里获得max:
eufgjt7s7#
我写了一篇关于这个的博客,看看吧:
http://www.nimrodstech.com/scala-map-merge/
基本上使用scalaz半组你可以很容易地实现这一点
看起来像这样:
kokeuurv8#
一个oneliner helper-func,它的用法几乎和scalaz一样简洁:
为了最终的可读性,将其 Package 在隐式自定义类型中:
iswrvxsc9#