Reputation: 9
Suppose a set of three lists:
val = [1 2 2 3 5 5 5 6 8]
m = ['m2' 'm1' 'm2' 'm2' 'm1' 'm2' 'm2' 'm1' 'm1']
v = ['v9' 'v3' 'v7' 'v5' 'v1' 'v6' 'v8' 'v2' 'v4']
I'm trying to a create a nested dictionary where each element in val is used as a first order key. The elements in m shall describe the second order keys.
I already found out how to create the nested dictionary with
d = {}
for x, y, z in zip(val, m, v):
d.setdefault(x,{})[y] = []
that creates the following structure
{1: {'m2': []}, 2: {'m2': [], 'm1': []}, 3: {'m2': []}, 5: {'m2': [], 'm1': []}, 6: {'m1': []}, 8: {'m1': []}}
And if i append z with
d.setdefault(x,{})[y].append(z)
i get
{1: {'m2': ['v9']}, 2: {'m2': ['v7'], 'm1': ['v3']}, 3: {'m2': ['v5']}, 5: {'m2': ['v8'], 'm1': ['v1']}, 6: {'m1': ['v2']}, 8: {'m1': ['v4']}}
I also know how to create a dictionary that assigns the elements of v to the corresponding first order keys (i.e. the elements of val)
for elem in range(len(val)):
if val[elem] not in d:
d[val[elem]] = []
d[val[elem]].append(v[elem])
resulting in
{1: ['v9'], 2: ['v3', 'v7'], 3: ['v5'], 5: ['v1', 'v6', 'v8'], 6: ['v2'], 8: ['v4']}
However i fail to see the last step to get the desired output:
{1: {'m2': ['v9']}, 2: {'m2': ['v7'], 'm1': ['v3']}, 3: {'m2': ['v5']}, 5: {'m2': ['v6', 'v8'], 'm1': ['v1']}, 6: {'m1': ['v2']}, 8: {'m1': ['v4']}}
(the element 'v6' is missing in the subdictionary with the key '5' and second order key 'm2' (i.e. 5: {'m2': ['v8']})
Upvotes: 0
Views: 105
Reputation: 26039
Use itertools.groupby
and zip
with a nested dictionary-comprehension.
Example:
from itertools import groupby
val = [1, 2, 2, 3, 5, 5 ,5, 6, 8]
m = ['m2', 'm1', 'm2' ,'m2', 'm1', 'm2', 'm2', 'm1' ,'m1']
v = ['v9', 'v3' ,'v7', 'v5', 'v1', 'v6', 'v8', 'v2', 'v4']
f1 = lambda x: x[:2]
f2 = lambda x: x[0]
print({k: {x[1]: [z[2] for z in y] for x, y in groupby(sorted(g, key=f1), f1)} for k, g in groupby(sorted(zip(val, m, v), key=f2), key=f2)})
# {1: {'m2': ['v9']}, 2: {'m1': ['v3'], 'm2': ['v7']}, 3: {'m2': ['v5']}, 5: {'m1': ['v1'], 'm2': ['v6', 'v8']}, 6: {'m1': ['v2']}, 8: {'m1': ['v4']}}
Upvotes: 1
Reputation: 11
Try to use defaultdict
from collections import defaultdict
val = [1, 2, 2, 3, 5, 5, 5, 6, 8]
m = ['m2', 'm1', 'm2', 'm2', 'm1', 'm2', 'm2', 'm1', 'm1']
v = ['v9', 'v3', 'v7', 'v5', 'v1', 'v6', 'v8', 'v2', 'v4']
dd = defaultdict(lambda: defaultdict(list))
for k1, k2, k3 in zip(val, m, v):
dd[k1][k2].append(k3)
dd
Upvotes: 1