我想对包含值列表的HashMap进行转换,以生成具有单个值的所有组合。
示例
Suma: <xsl:value-of select="sum(@price)"/>
预期结果是
hm = [x : [1,2], y : ['a','b'] ]
到目前为止,我想出了这种方法
res = [ [x: 1, y : 'a'],
[x: 1, y : 'b'],
[x: 2, y : 'a'],
[x: 2, y : 'b']
]
这可行,但是取决于HashMap中键的名称和数量,因此
println hm.values().combinations().collect{[x:it[0],y:it[1]]}
[[x:1, y:a], [x:2, y:a], [x:1, y:b], [x:2, y:b]]
我必须重写为
hm = [u : [1,2], w : ['a','b'] , z : ['X','Y']]
是否存在所有密钥名称和数字的通用解决方案?
答案 0 :(得分:3)
您可以将闭包传递给.combinations()
方法以转换当前组合。然后,您可以使用[[a,b,c], [1,2,3]].transpose()
来将两个列表中的值“压缩”在一起(例如,下例中的[[a,1],[b,2],[c,3]]
),然后可以使用.collectEntries()
将此类对的列表转换为映射。 / p>
考虑以下示例:
def hm = [x : [1,2], y : ['a','b'] ]
def combs = hm.values().combinations { args ->
[hm.keySet().asList(), args].transpose().collectEntries { [(it[0]): it[1]]}
}
combs.each {
println it
}
输出:
[x:1, y:a]
[x:2, y:a]
[x:1, y:b]
[x:2, y:b]
现在,我们可以在输入映射中添加另一个键,该代码将按预期工作:
def hm = [x : [1,2], y : ['a','b'], z: ['X','Y'] ]
def combs = hm.values().combinations { args ->
[hm.keySet().asList(), args].transpose().collectEntries { [(it[0]): it[1]]}
}
combs.each {
println it
}
输出:
[x:1, y:a, z:X]
[x:2, y:a, z:X]
[x:1, y:b, z:X]
[x:2, y:b, z:X]
[x:1, y:a, z:Y]
[x:2, y:a, z:Y]
[x:1, y:b, z:Y]
[x:2, y:b, z:Y]
使代码更加优雅之后的最后一个示例可能看起来像这样:
def hm = [z : [2,1], y : ['a','b'], x: ['C','B']]
def values = hm.values()
def keys = hm.keySet().toList()
def map = values.combinations { args ->
[keys, args].transpose().collectEntries { [(it[0]): it[1]]}
}
println map
它打印:
[[z:2, y:a, x:C], [z:1, y:a, x:C], [z:2, y:b, x:C], [z:1, y:b, x:C], [z:2, y:a, x:B], [z:1, y:a, x:B], [z:2, y:b, x:B], [z:1, y:b, x:B]]
关于键和值排序的另一条评论。 Groovy使用的默认地图实现是LinkedHashMap
,它保证了条目的顺序(它们被添加的顺序)。这意味着:
map.values()
返回一个LinkedHashMap$LinkedValues
map.keySet()
返回一个LinkedHashMap$LinkedKeySet
在我们的示例中,仅由于keys
方法需要一个列表列表,所以我们不得不将hm.keySet().toList()
变量定义为transpose()
。
答案 1 :(得分:2)
您可以使用键组合和值组合:
def result = []
hm.entrySet().eachCombination { combination ->
combination.collect{it.value}
.eachCombination {
def entry = [:]
for(int i = 0; i < hm.size(); i++) {
entry.put(combination[i].key, it[i])
}
result << entry
}
println result
}
根据提供的输入将result
设置为[[x:1, y:a], [x:2, y:a], [x:1, y:b], [x:2, y:b]]
简单的逻辑是:找到键/值对的所有组合,然后对每一对,组合值以保持原始键/值对的顺序。
这适用于动态输入图。
给出hm = [x : [1, 2], y : ['a', 'b'], z: ['e', 'f']]
,结果为:
[[x:1, y:a, z:e],
[x:2, y:a, z:e],
[x:1, y:b, z:e],
[x:2, y:b, z:e],
[x:1, y:a, z:f],
[x:2, y:a, z:f],
[x:1, y:b, z:f],
[x:2, y:b, z:f]]