Looking for the easiest way to add values in subdictionaries. An example:
dict1 = {
"l": {"a": 1, "b": 2, "c": 3},
"s": {"a": 4, "b": 5, "c": 6},
"d": {"a": 7, "b": 8, "c": 9} }
I want to create output:
{"a": [1, 4, 7], "b": [2, 5, 8], "c": [3, 6, 9]}
Stuff that doesn't work:
from collections import defaultdict
dict1 = {
"l": {"a": 1, "b": 2, "c": 3},
"s": {"a": 4, "b": 5, "c": 6},
"d": {"a": 7, "b": 8, "c": 9} }
new_dict = defaultdict(list)
for k in dict1:
d2 = dict1.get(k)
for k, v in d2.items():
new_dict[k].append[v]
Output: TypeError: 'builtin_function_or_method' object is not subscriptable
I did also something like this:
dict1 = {
"l": {"a": 1, "b": 2, "c": 3},
"s": {"a": 4, "b": 5, "c": 6},
"d": {"a": 7, "b": 8, "c": 9} }
final_dict = {}
# list_dict = []
for k, v in dict1.items():
dict_new = dict1[k]
list_dict = []
for new_k, new_v in dict_new.items():
list_dict.append(new_v)
final_dict[new_k] = list_dict
print("list_dict ", list_dict)
print("final_dict", final_dict)
...but the output is:
{'a': [7, 8, 9], 'b': [7, 8, 9], 'c': [7, 8, 9]}
When I put list_dict = []
outside for loop, then the output is:
{'a': [1, 2, 3, 4, 5, 6, 7, 8, 9], 'b': [1, 2, 3, 4, 5, 6, 7, 8, 9], 'c': [1, 2, 3, 4, 5, 6, 7, 8, 9]}
I wonder do I need some sort of recursion method here to group by all sub-keys (a, b, c) and append all related values, or maybe there is a need for dictionary comprehension.
CodePudding user response:
The output suggests you want to loop over the values of dict1
. One option is to use collections.defaultdict
:
from collections import defaultdict
out = defaultdict(list)
for d in dict1.values():
for k,v in d.items():
out[k].append(v)
out = dict(out)
Another option is to use cytoolz.dicttoolz.merge_with
:
from cytoolz.dicttoolz import merge_with
out = merge_with(list, *dict1.values())
Yet another option is to use operator.itemgetter
in a comprehension:
from operator import itemgetter
vals = list(dict1.values())
keys = chain.from_iterable(map(dict.keys, vals))
out = {k: list(map(itemgetter(k), vals)) for k in keys}
Output:
{'a': [1, 4, 7], 'b': [2, 5, 8], 'c': [3, 6, 9]}
CodePudding user response:
new_dict[k].append[v]
should be new_dict[k].append(v)
- you're not calling the method (as you should), you're trying to index into it as a list/dict. There is also no reason to look up the value of k
in the dict immediately after iterating it - you can use values()
to get only the values instead.
for inner_dict in dict1.values():
for k, v in inner_dict.items():
new_dict[k].append(v)
CodePudding user response:
Adding to the previous answers, if you wished to do this in an one-liner you could do it as such:
dict1 = {
"l": {"a": 1, "b": 2, "c": 3},
"s": {"a": 4, "b": 5, "c": 6},
"d": {"a": 7, "b": 8, "c": 9}
}
out = dict(zip(dict1.keys(), map(list, zip(*map(dict.values, dict1.values())))))
print(out)
Output:
{'l': [1, 4, 7], 's': [2, 5, 8], 'd': [3, 6, 9]}