I would like to join two dictionaries using Python. Given:
dict_keys = {"A": ["A1", "A2"], "B": ["B1", "B2"], "C": ["C1"]}
dict_values1 = {"A1": [1, 2, 3, 4], "A2": [5, 6, 7], "B1": [8, 9], "B2": [10], "C1" : [11, 12, 13]}
dict_values2 = {"A1": ["one", "two", "three", "four"], "A2": ["five", "six", "seven"], "B1": ["eight", "nine"], "B2": ["ten"], "C1": ["eleven", "twelve", "thirteen"]}
I would like to join using the elements in the list of the value of dict_keys with dict_values1 and generate this:
{'A': [1, 2, 3, 4, 5, 6, 7], 'B': [8, 9, 10], 'C': [11, 12, 13]}
I would also like to join using the elements in the list of the value of dict_keys with dict_value2 and generate this:
{'A': ['one', 'two', 'three', 'four', 'five', 'six', 'seven'], 'B': ['eight', 'nine', 'ten'], 'C': ['eleven', 'twelve', 'thirteen']}
The code I wrote is simple:
def join():
dict_keys = {"A": ["A1", "A2"], "B": ["B1", "B2"], "C": ["C1"]}
dict_values1 = {"A1": [1, 2, 3, 4], "A2": [5, 6, 7], "B1": [8, 9], "B2": [10], "C1" : [11, 12, 13]}
dict_values2 = {"A1": ["one", "two", "three", "four"], "A2": ["five", "six", "seven"], "B1": ["eight", "nine"], "B2": ["ten"], "C1": ["eleven", "twelve", "thirteen"]}
result1 = {}
result2 = {}
for master_key, keys in dict_keys.items():
values1 = []
values2 = []
for key in keys:
values1.extend(dict_values1[key])
values2.extend(dict_values2[key])
result1[master_key] = values1
result2[master_key] = values2
return result1, result2
However, I think this implementation is not very "Python". So I changed it using comprehension:
def join():
dict_keys = {"A": ["A1", "A2"], "B": ["B1", "B2"], "C": ["C1"]}
dict_values1 = {"A1": [1, 2, 3, 4], "A2": [5, 6, 7], "B1": [8, 9], "B2": [10], "C1" : [11, 12, 13]}
dict_values2 = {"A1": ["one", "two", "three", "four"], "A2": ["five", "six", "seven"], "B1": ["eight", "nine"], "B2": ["ten"], "C1": ["eleven", "twelve", "thirteen"]}
result1 = {master_key: sum([dict_values1[key] for key in keys], []) for master_key, keys in dict_keys.items()}
result2 = {master_key: sum([dict_values2[key] for key in keys], []) for master_key, keys in dict_keys.items()}
return result1, result2
The problem of this implementation is that it needs to iterate through the dict_keys twice. But this is the farest I can get.
Can someone let me know if there are simpler and cleaner way to achieve this using just one iteration on dict_keys?
CodePudding user response:
Use dict.setdefault
method:
def dict_join(dict_keys, dict_values1):
d1 = {}
for k,v in dict_keys.items():
for x in v:
d1.setdefault(k,[]).extend(dict_values1[x])
return d1
result1 = dict_join(dict_keys, dict_values1)
result2 = dict_join(dict_keys, dict_values2)
Output:
{'A': [1, 2, 3, 4, 5, 6, 7], 'B': [8, 9, 10], 'C': [11, 12, 13]}
{'A': ['one', 'two', 'three', 'four', 'five', 'six', 'seven'],
'B': ['eight', 'nine', 'ten'],
'C': ['eleven', 'twelve', 'thirteen']}
CodePudding user response:
I can't think of great names today...
def do_it(keys, values):
from itertools import chain
for out_key, keys in keys.items():
yield out_key, list(chain.from_iterable(values[key] for key in keys))
print(dict(do_it(dict_keys, dict_values1)))
print(dict(do_it(dict_keys, dict_values2)))
Output:
{'A': [1, 2, 3, 4, 5, 6, 7], 'B': [8, 9, 10], 'C': [11, 12, 13]}
{'A': ['one', 'two', 'three', 'four', 'five', 'six', 'seven'], 'B': ['eight', 'nine', 'ten'], 'C': ['eleven', 'twelve', 'thirteen']}