7

I made a mistake in my question here (wrong requested input and expected output): Comparing dicts, updating NOT overwriting values

I am not looking for this solution: Combining 2 dictionaries with common key So this question is not a duplicate

Problem statement:

requested input:

d1 = {'a': ['a'], 'b': ['b', 'c']}
d2 = {'b': ['c', 'd'], 'c': ['e','f']}

expected output (I don't care about the order of the keys / values!):

new_dict = {'a': ['a'], 'b': ['b', 'c', 'd'], 'c': ['e', 'f']}

The solution in Combining 2 dictionaries with common key gives following output:

new_dict = {'a': ['a'], 'b': ['b', 'c', 'c', 'd'], 'c': ['e', 'f']}

I don't want the duplicates to be stored.

My solution (it works but it is not so efficient):

unique_vals = []
new_dict = {}
for key in list(d1.keys())+list(d2.keys()) :
    unique_vals = []
    try:
        for val in d1[key]:
            try:
                for val1 in d2[key]:
                    if(val1 == val) and (val1 not in unique_vals):
                        unique_vals.append(val)
            except:
                continue
    except:        
        new_dict[key] = unique_vals
    new_dict[key] = unique_vals


for key in d1.keys():
    for val in d1[key]:
        if val not in new_dict[key]:
            new_dict[key].append(val)
for key in d2.keys():
    for val in d2[key]:
        if val not in new_dict[key]:
            new_dict[key].append(val)
aze45sq6d
  • 876
  • 3
  • 11
  • 26

4 Answers4

7

Here is how I would go about it:

d1 = {'a': ['a'], 'b': ['b', 'c']}
d2 = {'b': ['c', 'd'], 'c': ['e','f']}
dd1 = {**d1, **d2}
dd2 = {**d2, **d1}
{k:list(set(dd1[k]).union(set(dd2[k]))) for k in dd1}

Produces the desired result.

quest
  • 3,576
  • 2
  • 16
  • 26
5

I suggest using a default dictionary collection with a set as a default value. It guarantees that all values will be unique and makes the code cleaner.

Talking about efficiecy it's O(n^2) by time.

   from collections import defaultdict


   d1 = {'a': ['a'], 'b': ['b', 'c']}
   d2 = {'b': ['c', 'd'], 'c': ['e','f']}

   new_dict = defaultdict(set)

   for k, v in d1.items():
       new_dict[k] = new_dict[k].union(set(v))

   for k, v in d2.items():
       new_dict[k] = new_dict[k].union(set(v))

Max Voitko
  • 1,542
  • 1
  • 17
  • 32
3

Try this code. You can remove deep copy if modifications in the initial array are fine for you.

import copy


def merge(left, right):
    res = copy.deepcopy(left)

    for k, v in right.items():
        res[k] = list(set(res[k]).union(v)) if k in res else v

    return res
Alex Tonkonozhenko
  • 1,514
  • 12
  • 26
2

Simple if statement if you don't want to use a Set.

d3 = dict(d2)
for k,v in d1.items():
    if k not in d3:
        d3[k] = v
    else:
        for n in d1[k]:
            if n not in d3[k]:
                d3[k].append(n)

Tom King
  • 21
  • 2