4

How could dictionaries whose values are lists be merged in Python, so that all of the keys are moved into one dictionary, and all the elements of each list moved into a single list for each key?

For example, with these dictionaries:

x = {'a': [2], 'b': [2]}
y = {'b': [11], 'c': [11]}

... the result of the merging should be like this:

{'a': [2], 'b': [2, 11], 'c': [11]}

How could this be done with any number of dictionaries, not just two?

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
shaziya
  • 101
  • 1
  • 8

5 Answers5

5

You can use following approach, which uses sets and dict comprehension

x = {'a': [2], 'b': [2]} 
y = {'b': [11], 'c': [11]}

all_keys = set(x) | set(y)

print {k:x.get(k, [])+y.get(k, []) for k in all_keys}

Results:

{'a': [2], 'c': [11], 'b': [2, 11]}
Tanveer Alam
  • 5,185
  • 4
  • 22
  • 43
  • 1
    `all_keys = set(x) | set(y)` would work in both 2 and 3. – DSM May 16 '15 at 15:39
  • Thanks @DSM Plus I even don't like `.keys()` method. – Tanveer Alam May 16 '15 at 15:44
  • @DSM Missed that :) – Tanveer Alam May 16 '15 at 15:46
  • Why not just get rid of all_keys? The expression is short/easy enough to just put in the comprehension directly. – Stefan Pochmann May 16 '15 at 15:46
  • 1
    @StefanPochmann: ehh, not worth worrying about. Plus if we wanted to do the generalized version (with an arbitrary number of dicts) it would be clearer to work with separate variables anyhow. – DSM May 16 '15 at 15:48
  • @StefanPochmann: That's just to make the statements more understandable. – Tanveer Alam May 16 '15 at 15:49
  • @DSM Someone (not the OP) actually just changed the question to the general case, pretending it to be *"formatting, removed unclear explanation"*. Is that ok? It invalidates all answers. – Stefan Pochmann May 16 '15 at 16:08
  • @Stefan OP did in fact ask for a solution for N dictionaries in the unedited question: "and the result should turn out to be like this, but **how do I work this out with any amount of dictionaries**" (my emphasis). – Zero Piraeus May 16 '15 at 18:43
  • @ZeroPiraeus Oh, right, I missed that as it was kinda hidden and the edit moved it elsewhere. I'm not convinced this is what the OP meant, though, since the title clearly and specifically asked about *two* dictionaries and the OP clearly didn't know how to do that. I suspect he didn't actually mean number of dictionaries there, but *size* of dictionaries or number of lists inside them or so. – Stefan Pochmann May 16 '15 at 19:04
5
for k, v in y.items():
    x.setdefault(k, []).extend(v)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
4

To collect all the lists together, form a result dictionary that maps your keys to lists. The simplest way to do this is with dict.setdefault() followed by a call to list.extend to grow the lists:

r = {}
for d in [x, y]:
    for k, v in d.items():
        r.setdefault(k, []).extend(v)

A little more elegant way is with collections.defaultdict() where the automatic default is a new empty list:

from collections import defaultdict

r = defaultdict(list)
for d in [x, y]:
    for k, v in d.items():
        r[k].extend(v)
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
1

Here's a solution that works for an arbitrary number of dictionaries:

def collect(*dicts):
    result = {}
    for key in set.union(*(set(d) for d in dicts)):
        result[key] = sum((d.get(key, []) for d in dicts), [])
    return result

It's essentially a generalisation of Tanveer's answer, taking advantage of the fact that set.union() can accept any number of dictionaries as arguments.

Here's an example of the function in use:

>>> x = {'a': [2], 'b': [2]}
>>> y = {'b': [11], 'c': [11]}
>>> collect(x, y)
{'a': [2], 'c': [11], 'b': [2, 11]}

... and with multiple dictionaries:

>>> z = {'c': [12, 13], 'd': [5]}
>>> collect(x, y, z)
{'a': [2], 'c': [11, 12, 13], 'b': [2, 11], 'd': [5]}
Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
0

x = {'a': [2], 'b': [2]}
y = {'b': [11], 'c': [11]}
result = {}
for key,value in x.iteritems():
    result[key] = value
for key,value in y.iteritems():
    if key in result:
        for l in value:
            result[key].append(l)
    else:
        result[key] = value
print result
shruti1810
  • 3,920
  • 2
  • 16
  • 28