3

I want merge two dict like this:

from:

  a1 = {u'2016-03-11': [u'20:00', u'22:10']}
  a2 = {u'2016-03-11': [u'20:00', u'23:10'],u'2016-03-12': [u'20:00', u'22:10']}

to:

  an = {u'2016-03-11': [u'20:00',u'22:10', u'23:10'],u'2016-03-12': [u'20:00', u'22:10']}

i need a function merge two dict

6 Answers 6

1
from collections import defaultdict


a1 = {u'2016-03-11': [u'20:00', u'22:10']}
a2 = {u'2016-03-11': [u'20:00', u'23:10'],u'2016-03-12': [u'20:00', u'22:10']}    

dd = defaultdict(set)
for d in a1, a2:
    for k, v in d.items():
        dd[k] |= set(v)
res = {k: sorted(v) for k, v in dd.items()}

print(res)
# {'2016-03-12': ['20:00', '22:10'], '2016-03-11': ['20:00', '22:10', '23:10']}
1
  • 1
    sorted(list(v)) can be reduced to sorted(v)
    – falsetru
    Commented Mar 16, 2016 at 9:16
1
a1 = {u'2016-03-11': [u'20:00', u'22:10']}
a2 = {u'2016-03-11': [u'20:00', u'23:10'],u'2016-03-12': [u'20:00', u'22:10']}


import copy
an = copy.deepcopy(a1)

for key, value in a2.iteritems():
    if key in an:
        an[key] = list(set(an[key] + a2[key]))
    else:
        an[key] = value

print an

>> {u'2016-03-11': [u'22:10', u'20:00', u'23:10'], u'2016-03-12': [u'20:00', u'22:10']}
1

Using set, sorted to combine to two list into one and to sort:

>>> a1 = {u'2016-03-11': [u'20:00', u'22:10']}
>>> a2 = {u'2016-03-11': [u'20:00', u'23:10'],u'2016-03-12': [u'20:00', u'22:10']}


>>> an = {}
>>> for d in a1, a2:
...     for key in d:
...         an[key] = sorted(set(an.get(key, []) + d[key]))
...         # ^^  Merge two lists (dictionary values) into one, and sort
... 
>>> print an
{u'2016-03-11': [u'20:00', u'22:10', u'23:10'],
 u'2016-03-12': [u'20:00', u'22:10']}

UPDATE

alternative version using dictionary comprehension (assuming merging only two dictionaries):

>>> {key: sorted(set(a1.get(key,[]) + a2.get(key,[]))) for key in set(a1)|set(a2)}
{u'2016-03-11': [u'20:00', u'22:10', u'23:10'],
 u'2016-03-12': [u'20:00', u'22:10']}
3
  • if don't use the 'for' and how can i do??
    – Vity Lin
    Commented Mar 16, 2016 at 8:48
  • @VityLin, You need to iterate dictionary any way. It's inevitable.
    – falsetru
    Commented Mar 16, 2016 at 8:57
  • @VityLin, I added a version that does not use for loop, but dictionary comprehension. (But it still iterates)
    – falsetru
    Commented Mar 16, 2016 at 9:25
1
a1 = {u'2016-03-11': [u'20:00', u'22:10']}
a2 = {u'2016-03-11': [u'20:00', u'23:10'],u'2016-03-12': [u'20:00', u'22:10']}


an = a1

for key in a2 :
    if key in an :
        an[key] = list(set(a2[key]+ a2[key]))
        an[key].sort()
    else :
        x = {key : a2[key]}
        an.update(x)

keyList = an.keys()
keyList.sort()
temp = {}
for key in keyList:
    temp.update({key:an[key]})

an = temp 
print an
0

I derived this option (posted here as an answer):

an = {}
for key in set().union(a1, a2): 
    an[key] = sorted(set().union(a1.get(key, []), a2.get(key, [])))

It builds the sets without list concatenations.

It produces the required result:

>>> a1 = {u'2016-03-11': [u'20:00', u'22:10']}
>>> a2 = {u'2016-03-11': [u'20:00', u'23:10'],u'2016-03-12': [u'20:00', u'22:10']}
>>> an = {}
>>> for key in set().union(a1, a2): 
...     an[key] = sorted(set().union(a1.get(key, []), a2.get(key, [])))
... 
>>> an
{u'2016-03-11': [u'20:00', u'22:10', u'23:10'], u'2016-03-12': [u'20:00', u'22:10']}
-1

It looks awful but it works:

an = {}
for key in set(list(a1.keys()) + list(a2.keys())):
    an[key] = list(set((a1.get(key) or []) + (a2.get(key) or [])))

I am shure there is more clever and pythonic way, though :)

3
  • 1
    Iterating dictionary yields keys: keys() is not necessary. Use dict.get(key, default) instead of dict.get(key) or default: for key in set(list(a1) + list(a2)): an[key] = list(set(a1.get(key, []) + a2.get(key, [])))
    – falsetru
    Commented Mar 16, 2016 at 9:14
  • 1
    1. a1.get(key, []) not (a1.get(key) or []) [get take default argument that is used when the key is not found] 2. set().union(a1.keys(), a2.keys()) (or set().union(a1.keys()).union(a2.keys()) if >2.6) not set(list(a1.keys()) + list(a2.keys())) [this avoids creating 3 lists and 1 set in exchange for 1 empty set and at most 2 partially filled ones]
    – Dan D.
    Commented Mar 16, 2016 at 9:15
  • 1
    And including what falsetru gives: for key in set().union(a1, a2): an[key] = list(set().union(a1.get(key, []), a2.get(key, [])))
    – Dan D.
    Commented Mar 16, 2016 at 9:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.