Reputation: 78
I'm wondering what is the best way to merge 2 dicts into one dict as follows:
dict1 = {k1: v1, k2: v2, ...}
and dict2 = {v1: w1, v2: w2, ...}
into
result = {k1: w1, k2: w2, ...}
I already have a solution using dict comprehension:
result = {
k: dict2[v]
for k, v in dict1.items()
}
But I don't think this is the most elegant way to do it. Can you please help me ?
Upvotes: 4
Views: 1806
Reputation: 82939
As an alternative/extension, to @jpp's answer, you could also use reduce
/functools.reduce
to get a slightly more condensed form of the chainer
function:
from functools import reduce
def chainer(first, *others):
return {k: reduce(lambda x, d: d[x], others, v) for k, v in first.items()}
Which of those is better is mainly a matter of taste; usage and results are the same.
For just two dictionaries, your dictionary comprehension is IMHO as good and elegant as it gets. You might want to use get
or add a condition in case a key is not present in the second dict, though.
>>> dict1 = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
>>> dict2 = {'v1': 'w1', 'v2': 'w2'}
>>> {k: dict2.get(v, 'undefined') for k, v in dict1.items()}
{'k1': 'w1', 'k2': 'w2', 'k3': 'undefined'}
>>> {k: dict2[v] for k, v in dict1.items() if v in dict2}
{'k1': 'w1', 'k2': 'w2'}
Adding a safeguard like this into the chainer
is a bit more involved, in particular for this variant using reduce
(and might not be necessary at all).
Upvotes: 4
Reputation: 164793
For the two-dictionary case, your dictionary comprehension is fine. This assumes you can guarantee your values in dict1
are keys in dict2
.
Considering how you can extend this to arbitrary dictionary inputs, you can use a for
loop:
dict1 = {'k1': 'v1', 'k2': 'v2'}
dict2 = {'v1': 'w1', 'v2': 'w2'}
dict3 = {'w1': 'x1', 'w2': 'x2'}
def chainer(first, *others):
res = first.copy() # make a copy to avoid overwriting dict1
for k, v in res.items():
for dct in others:
v = dct[v]
res[k] = v
return res
res = chainer(dict1, dict2, dict3)
# {'k1': 'x1', 'k2': 'x2'}
Upvotes: 4