在Groovy中添加两个映射,同时汇总公共键的值

use*_*956 19 groovy dictionary

我在Groovy两个地图[a: 1, b: 2][b:1, c:3]并想从他们创造一个第三张地图[a: 1, b: 3, c: 3].是否有Groovy命令可以做到这一点?

编辑:请注意,如果键相同,则第三个映射中的值是前两个映射的值的总和.

谢谢

tim*_*tes 16

另一种解决方案是:

def m1 = [ a:1, b:2 ]
def m2 = [ b:1, c:3 ]

def newMap = [m1,m2]*.keySet().flatten().unique().collectEntries {
  [ (it): [m1,m2]*.get( it ).findAll().sum() ]
}
Run Code Online (Sandbox Code Playgroud)

流行病学家的答案视为鼓舞人心,您还可以编写一种方法来处理多个地图

def m1 = [a: 1, b: 2]
def m2 = [b: 1, c: 3]

def combine( Map... m ) {
  m.collectMany { it.entrySet() }.inject( [:] ) { result, e ->
    result << [ (e.key):e.value + ( result[ e.key ] ?: 0 ) ]
  }
}

def newMap = combine( m1, m2 )
Run Code Online (Sandbox Code Playgroud)

  • 我认为提供一个带有漂亮签名的完整方法,就像你的第二个例子(而不是抛出的表达式)真的会增加一点响应的整体质量,因为我们应该如何在"真实"中编写这些东西"代码,如果我们担心代码质量.+1 = D. (3认同)

epi*_*ian 13

这适用于任意数量的地图:

def maps = [[a: 1, b: 2], [b:1, c:3]]

def result = [:].withDefault{0}
maps.collectMany{ it.entrySet() }.each{ result[it.key] += it.value }

assert result == [a: 1, b: 3, c: 3]
Run Code Online (Sandbox Code Playgroud)

maps.collectMany{ it.entrySet() }表达式返回映射条目,像的列表[a=1, b=2, b=1, c=3],然后将每个这些被添加到结果.

另一种选择,如果你想将所有转换保持在一个表达式并使其"更具功能性",则首先按键对条目进行分组,然后对值进行求和,但我认为它的可读性较差:

def result = maps.collectMany{ it.entrySet() }
    .groupBy{ it.key }
    .collectEntries{[it.key, it.value.sum{ it.value }]}
Run Code Online (Sandbox Code Playgroud)

groupBy部分返回表单的地图,[a:[a=1], b:[b=2, b=1], c:[c=3]]然后返回collectEntries映射到具有相同kays但具有值中列表总和的另一个变换.