I have two maps in Groovy [a: 1, b: 2]
and [b:1, c:3]
and would like to create from them a third map [a: 1, b: 3, c: 3]
. Is there a Groovy command that does that?
Edit: Notice that the values in the third map, are a sum of the values from the first two maps, if the keys are identical.
Thanks
The easiest way to merge two maps in Groovy is to use + operator. This method is straightforward - it creates a new map from the left-hand-side and right-hand-side maps.
Map Declaration You have two options to declare a map in groovy. First option is, define an empty map and put key-value pairs after. Second option is declaring map with default values.
A hashmap maps a key to a value, but you are trying to map a key to two values. To do this, create a hashmap, where the key is your ID and the value is another hashmap, mapping the string "firstname" to "Jack" and the string "lastname" to "Sparrow" and so on for all <person> elements. Morten.
Yet another solution would be:
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() ]
}
Taking epidemian's answer as inspiriation, you can also write a method to handle multiple maps
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 )
This should work for any number of maps:
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]
The maps.collectMany{ it.entrySet() }
expression returns a list of map entries, like [a=1, b=2, b=1, c=3]
, and then each of those is added to the result.
Another option, if you'd like to keep all the transformation into one expression and make it "more functional", is to first group the entries by key and then sum the values, but I think it's less readable:
def result = maps.collectMany{ it.entrySet() }
.groupBy{ it.key }
.collectEntries{[it.key, it.value.sum{ it.value }]}
The groupBy
part returns a map of the form [a:[a=1], b:[b=2, b=1], c:[c=3]]
and then the collectEntries
transforms that map into another one that has the same kays but has the sum of the lists in the values instead.
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