7
\$\begingroup\$

I have two dictionaries and a merged dictionary:

dict1 = {-3: 0.3, -2: 0.1, 1: 0.8} dict2 = {0: 0.3, 1: 0.5, -1: 0.7} dict_merged = {} 

I have code that basically merges the two together by adding keys together and multiplying values: e.g.

for k1, v1 in dict1.items(): for k2, v2 in dict2.items(): new_key = k1 + k2 if new_key in dict_merged: dict_merged[new_key] += v1 * v2 else: dict_merged[new_key] = v1 * v2 

Is there a faster way to do this, it feels like there should but dict comprehension doesn't seem helpful here. In the above example, we are going to get several contributes to the key "-3" for example.

\$\endgroup\$
3
  • 1
    \$\begingroup\$Be advised that in Python<3.7 the order of the keys are not guaranteed. Your code might work in your PC, but in someone else's might break horribly.\$\endgroup\$
    – pepoluan
    CommentedMar 11, 2020 at 1:59
  • 2
    \$\begingroup\$@pepoluan strange advice, since the code here doesn't require the dictionaries to be sorted.\$\endgroup\$
    – Peilonrayz
    CommentedMar 11, 2020 at 11:46
  • \$\begingroup\$@Peilonrayz ahh okay I misread the code somehow. My bad.\$\endgroup\$
    – pepoluan
    CommentedMar 24, 2020 at 11:34

1 Answer 1

18
\$\begingroup\$

It's standard to indent Python with 4 spaces. Not following this standard only makes your life and the life of people that have to interact with you harder.

You can just use the optional default argument to dict.get to remove the need for the if.

for k1, v1 in dict1.items(): for k2, v2 in dict2.items(): key = k1 + k2 dict_merged[key] = v1 * v2 + dict_merged.get(key, 0) 

Alternately you can change dict_merged to a collections.defaultdict, rather than a dict. This removes the need to use dict.get, and allows you to just us +=. defaultdict takes a function that provides the default value to use. Since int() returns 0, we can just pass int as the function. As noted by Ilmari Karonen you can also use float as that returns 0.0 without any arguments.

import collections dict_merged = collections.defaultdict(int) for k1, v1 in dict1.items(): for k2, v2 in dict2.items(): dict_merged[k1 + k2] += v1 * v2 
\$\endgroup\$
7
  • 1
    \$\begingroup\$Thank you very much! I didn't know you could default a get value.\$\endgroup\$
    – gjdpm1
    CommentedMar 10, 2020 at 16:58
  • \$\begingroup\$float with no arguments also returns 0.0 and would probably be a more appropriate default factory for the OP, since their actual values all seem to be floats.\$\endgroup\$CommentedMar 11, 2020 at 15:35
  • 2
    \$\begingroup\$I really wouldn't recommend defaultdict (at least without changing it back into a normal dict), since later on when you actually use it, you'll get 0 instead of a key error when you try to get something that's not there.\$\endgroup\$CommentedMar 11, 2020 at 15:57
  • \$\begingroup\$@Noctiphobia I've used defaultdict plenty of times, and haven't experienced that issue.\$\endgroup\$
    – Peilonrayz
    CommentedMar 11, 2020 at 16:07
  • 1
    \$\begingroup\$@Cal And that's why I provided two alternates...\$\endgroup\$
    – Peilonrayz
    CommentedMar 11, 2020 at 18:10

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.