Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If keys of two dictionaries are equal, perform operation using both values and move to new dict (python)

I have two dictionaries, like this:

d1 = {'red':10, 'blue':20, 'green':30, 'yellow':40}
d2 = {'red':1, 'blue':2, 'green':3}

I want go through each item in d1 and see if the key matches a key in d2. If so, I want to subtract the d2 key from the d1 key, and move the new key/value pair into a new dictionary, resulting in:

d3 = {'red':9, 'blue':18, 'green':27, 'yellow':40}

I wrote the following script to do this:

for x, y in d1.items():
    for a, b in d2.items():
        if x == a:
            d3[x] = (y-b)
        elif x not in d2.items():
            d3[x] = y

This works, but when I try to use this on two dictionaries with thousands of items, the function never finishes. I guess it's way too slow.

Can you recommend a better way to do this? Thanks a lot.

like image 485
lambda_xx Avatar asked Dec 14 '22 22:12

lambda_xx


2 Answers

Yes, you make things too complicated, simply use dictionary comprehension:

{k:v1-d2.get(k,0) for k,v1 in d1.items()}

This will generate:

>>> {k:v1-d2.get(k,0) for k,v1 in d1.items()}
{'red': 9, 'blue': 18, 'green': 27, 'yellow': 40}

The code works as follows: the dictionary comprehension will iterate through the items() of d1, with k the key and v1 the value of d1 that is associated with k.

Then for each such key-value pair, we will associate v1-d2.get(k,0) with the key k in the resulting dictionary. d2.get(k,0) will aim to fetch the value associated with k, and if the key is not in the dictionary, it will return 0.

The algorithm runs - given dictionary lookup can happen in O(1) (not guaranteed, but very likely) - in O(n) with n the number of elements in d1, so reasonably fast.

like image 147
Willem Van Onsem Avatar answered Dec 28 '22 06:12

Willem Van Onsem


You can use dict comprehension with an if-else statement:

d1 = {'red':10, 'blue':20, 'green':30, 'yellow':40}
d2 = {'red':1, 'blue':2, 'green':3}

new_dict = {a:b-d2[a] if a in d2 else b for a, b in d1.items()}

Output:

{'blue': 18, 'green': 27, 'red': 9, 'yellow': 40}
like image 40
Ajax1234 Avatar answered Dec 28 '22 07:12

Ajax1234