3

The two dictionaries mydict1 and mydict2 are given. Key-value-pairs in mydict2 should be removed if the values are already contained in mydict1, regardless of the key and regardless of the order of the values.

The code below delivers the correct output mydict2 = {'key6': [2,1,4], 'key4': [2]}. However, it will be used as part of a larger code. Is there is a better, i.e. more phytonic, way to write it in order to make it more compact and effective without the need of functions?

mydict1 = {'key1':[1],'key2':[1,2],'key3':[1,2,3]}
mydict2 = {'key4':[2],'key5':[2,1],'key6':[2,1,4]}
mydict3 = {}

for md2 in mydict2:
    isindict = False
    for md1 in mydict1:
        isindict = isindict|(sorted(mydict1[md1])==sorted(mydict2[md2]))
    if not isindict:
        mydict3[md2] = mydict2[md2]
mydict2 = mydict3

The solutions for removing items from a list, comparison of dictionaries and conditional filtering of a dictionary are not transferable in a straightforward way.

stonebe
  • 482
  • 1
  • 3
  • 14

3 Answers3

1

Use a list comprehension and dict comprehension to sort all the values of mydict2 then check if the sorted value of mydict1 is in there:

mydict1 = {'key1':[1],'key2':[1,2],'key3':[1,2,3]}
mydict2 = {'key4':[2],'key5':[2,1],'key6':[2,1,4]}

vals = [tuple(sorted(x)) for x in mydict1.values()]
mydict2 = {k:v for (k,v) in mydict2.items() if tuple(sorted(v)) not in vals}

print(mydict2)

Or, in one line:

mydict1 = {'key1':[1],'key2':[1,2],'key3':[1,2,3]}
mydict2 = {'key4':[2],'key5':[2,1],'key6':[2,1,4]}

mydict2 = {k:v for (k,v) in mydict2.items() 
        if tuple(sorted(v)) not in [tuple(sorted(x)) for x in mydict1.values()]}

print(mydict2)
stonebe
  • 482
  • 1
  • 3
  • 14
Ruzihm
  • 19,749
  • 5
  • 36
  • 48
  • You are creating the same list of tuples for every key/value pair in `mydict1` – Peter Wood Nov 01 '19 at 16:08
  • @PeterWood If you want to memoize the list of tuples, then use the version with the extra line `vals=...` – Ruzihm Nov 01 '19 at 16:14
  • @PeterWood I guess I'm not sure what you're getting at because my answer only creates a single list of tuples in the first code example, not a list for each key/value pair. – Ruzihm Nov 01 '19 at 16:20
0

You can use dict comprehension :

mydict1 = {'key1':[1],'key2':[1,2],'key3':[1,2,3]}
mydict2 = {'key4':[2],'key5':[2,1],'key6':[2,1,4]}

results = {key : value for (key,value) in mydict2.items() 
           if set(value) not in [ set(val) for val in mydict1.values()]}
print(results)

{'key4': [2], 'key6': [2, 1, 4]}

Edit1

Doesn't work wiht duplicate like this :

mydict1 = {'key1':[1],'key2':[1,2],'key3':[1,2,3], 'key4' : [1, 1, 2]}
mydict2 = {'key4':[2],'key5':[2,1],'key6':[2,1,4], 'key7' : [2, 2, 1]}

Edit 2

Following @Ruzihm awsers and @Peter Wood comments :

mydict3 = {k:v for (k,v) in mydict1.items() 
        if tuple(sorted(v)) not in set(tuple(sorted(x)) for x in mydict2.values())}

This awser the OP question and avoid creating multiple time the same tuple of value as mentioned by @Peter Wood.

Florian Bernard
  • 2,561
  • 1
  • 9
  • 22
0

i think this will work:

mydict1 = {'key1':[1],'key2':[1,2],'key3':[1,2,3]}
mydict2 = {'key3':[2],'key5':[2,1],'key6':[2,1,4]}

def merge_two_dicts(x, y):
    z = x.copy()
    z.update(y) 
    return z

result = merge_two_dicts(mydict1, mydict2)
print(result)