Reputation: 1300
This is about Java, but for readability's sake, I'm going to write the examples down in JSON.
Say I have a List
of Map
s set up like this:
[{
"id": 1,
"foo": 12,
"bar": 34
}, {
"id": 1,
"baz": 56
}, {
"id": 2,
"foo": 78
}, {
"id": 2,
"bar": 90
}]
What I'd like to do is merge maps that have the same id
. Basically, I want to end up with something like this:
[{
"id": 1,
"foo": 12,
"bar": 34,
"baz": 56
}, {
"id": 2,
"foo": 78,
"bar": 90
}]
All other questions I found deal with merging maps in unrelated ways, and most are only concerned about two maps, not a variable amount.
This code seems to work, but strikes me as a little verbose:
List<Map<String, Integer>> toRemove = new ArrayList<Map<String, Integer>>();
for (Map<String, Integer> map : list) {
if (toRemove.contains(map)) {
continue;
}
int id = map.get("id");
for (Map<String, Integer> otherMap : list) {
if (map.equals(otherMap)) {
continue;
}
int otherId = otherMap.get("id");
if (id == otherId) {
map.putAll(otherMap);
toRemove.add(otherMap);
}
}
}
list.removeAll(toRemove);
Is there a more elegant way to achieve this?
Upvotes: 1
Views: 1739
Reputation: 2119
My сrazy solution with streams:
List<Map<String, Integer>> result = list.stream()
.collect(Collectors.groupingBy(m -> m.get("id")))
.values().stream()
.map(m -> m.stream().<Map<String, Integer>>collect(HashMap::new, Map::putAll, Map::putAll))
.collect(Collectors.toList());
Upvotes: 1
Reputation: 425
Just make a groupMap
that is a new Map, with id
is the key and element map is value:
List<Map<String, Integer>> toRemove = new ArrayList<Map<String, Integer>>();
Map<Integer, Map<String, Integer>> groupMap = new HashMap<>();
for (Map<String, Integer> m : toRemove) {
Integer id = m.get("id");
Map<String, Integer> tmp = groupMap.get(id);
if (tmp == null) {
groupMap.put(id, m);
} else {
tmp.putAll(m);
}
}
List<Map<String, Integer>> newList = new ArrayList<>(groupMap.values());
Then, the newList
is your result now.
Upvotes: 2
Reputation: 1614
I would organize the result in a Map
of Maps
Map<Integer, Map<String,Integer>> mapOfMaps = new HashMap<Integer, Map<String,Integer>>();
for(Map<String,Integer> map : list){
Integer id = map.get("id");
Map<String,Integer> existingMap = mapOfMaps.get(id);
if(existingMap == null){
mapOfMaps.put(id, map);
}else{
existingMap.putAll(map);
}
}
As I commented above: this in the case you don't need to sum values (apart from id
maps do not share other keys, or if they do values would be replaced)
Upvotes: 3