One way would be to loop through the input list (data
or newlist
) and use .setdefault
and .append
to fill up the nested dictionary or lists.
To get the nested dictionary from data
:
result, kList, vData = {}, data[0], data[1:]
for r in vData:
k_outer, k_inner = r[:2]
dict_inner = result.setdefault(k_outer, {})
list_inner = dict_inner.setdefault(k_inner, [])
list_inner.append(dict(zip(kList, r)))
To get the nested dictionary from newlist
:
# newlist = [dict(zip(data[0],r)) for r in data[1:]] # <-- get newlist from data
result, k_outer_key, k_inner_key = {}, 'num', 'e1'
for r in newlist:
k_outer, k_inner = r.get(k_outer_key), r.get(k_inner_key)
dict_inner = result.setdefault(k_outer, {})
list_inner = dict_inner.setdefault(k_inner, [])
list_inner.append(r)
You can also use dictionary comprehension to create a nested dictionary containing empty lists and then loop through data
or newlist
and add each dictionary in the input list to whichever list it belongs to in the nested dictionary.
(You could filter the input list for each nested key right away with list comprehension when you're defining the nested dictionary, but doing it in a separate loop actually reduces the total number of times you loop through the input data.)
To get the nested dictionary from data
, you can use
kList, vData = data[0], data[1:]
result = {k_outer: {
k_inner: [] for k, k_inner, *_ in vData if k==k_outer
} for k_outer in {k1 for k1, *_ in vData}}
for r in vData: result[r[0]][r[1]].append(dict(zip(kList,r)))
## OR
''' ## [SLIGHTLY LESS EFFICIENT]
kList, vData = data[0], data[1:]
result = {k_outer: {
k_inner: [dict(zip(kList,x)) for x in vData if x[0]==k_outer and x[1]==k_inner]
for k, k_inner, *_ in vData if k==k_outer
} for k_outer in {k1 for k1, *_ in vData}}
'''
To get the nested dictionary from newlist
, you can use
k_outer, k_inner = 'num', 'e1'
result = {k: {
d.get(k_inner): [] for d in newlist if k==d.get(k_outer)
} for k in {r.get(k_outer) for r in newlist}}
for r in newlist: result[r.get(k_outer)][r.get(k_inner)].append(r)
## OR
''' ## [SLIGHTLY LESS EFFICIENT]
k_outer, k_inner = 'num', 'e1'
result = {k: {d.get(k_inner): [
x for x in newlist if x.get(k_outer)==k and x.get(k_inner)==d.get(k_inner)
] for d in newlist if k==d.get(k_outer)} for k in {r.get(k_outer) for r in newlist}}
'''
Whichever approach is taken, result
should look like
{
'2004': {
'p': [{'num': '2004', 'e1': 'p', 'e2': 'a', 'e3': 'p'}, {'num': '2004', 'e1': 'p', 'e2': 's', 'e3': 'f'}]
},
'2002': {
'p': [{'num': '2002', 'e1': 'p', 'e2': 'r', 'e3': 'i'}],
'k': [{'num': '2002', 'e1': 'k', 'e2': 'r', 'e3': 'i'}]
},
'2001': {
'k': [{'num': '2001', 'e1': 'k', 'e2': 'r', 'e3': 'e'}]
}
}