I have two maps as:
firstMap = [totalProjectCount:53, activeProjectCount:29, completedProjectCount:1, userCount:85]
secondMap = [totalProjectCount:48, activeProjectCount:41, completedProjectCount:0, userCount:123]
and i need result such as:
resultMap = [totalProjectCount:101, activeProjectCount:70, completedProjectCount:1, userCount:208]
Yet another Groovy alternative:
def firstMap = [totalProjectCount:53, activeProjectCount:29, completedProjectCount:1, userCount:85, a:1]
def secondMap = [totalProjectCount:48, activeProjectCount:41, completedProjectCount:0, userCount:123, b:2]
def result = [firstMap, secondMap]*.keySet().flatten().toSet().collectEntries { k ->
[k, (firstMap[k] ?: 0) + (secondMap[k] ?: 0)]
}
assert result == [a:1, b:2, completedProjectCount:1, userCount:208, activeProjectCount:70, totalProjectCount:101]
This also works if you have values in one map that don't exist in the other (see a
and b
)
To make this a reusable part of your toolbelt, it's important, to extract the function you want to merge with.
The merging itself is then just the creation of a new map with all the keys of the maps and the values reduced with the passed function.
Map mergeWith(Closure fn, Map... maps) {
maps*.keySet().sum().collectEntries{k->
[k, maps.findAll{it.containsKey k}*.get(k).inject(fn)]
}
}
def m1 = [a:53, b:29, c:1, x:85]
def m2 = [a:48, b:41, c:0, y:123]
def m3 = [z:42]
// sum
assert mergeWith({a,b->a+b}, m1, m2, m3)==[a:101, b:70, c:1, x:85, y:123, z:42]
// product
assert mergeWith({a,b->a*b}, m1, m2, m3)==[a:2544, b:1189, c:0, x:85, y:123, z:42]
mergeWith
takes a reducing function (a function, that gets called with
two params and returns one value) and some maps. This means, you can a)
use it for other operations than just the sum and b) you can use it for
more than one map.
maps*.keySet().sum()
is the union of all keys. Then we
collectEntries
(build a new map) over that set of keys. For the value
find all maps, that contains the key (this makes this work nicely even
in cases, where the actual value is falsey) and fetch the values of k
via the spread operator. Then we reduce (oddly named inject
) the list
of values with the passed function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With