The following code works but it's very ungainly:
a = 0
for k in keys:
a = a 1
if a == 1:
k1 = k
if a == 2:
k2 = k
if a == 3:
k3 = k
if a == 1:
list_of_dict = sorted(list_of_dict, key = lambda ele: ele[k1], reverse = rev)
if a == 2:
list_of_dict = sorted(list_of_dict, key = lambda ele: ele[k1][k2], reverse = rev)
if a == 3:
list_of_dict = sorted(list_of_dict, key = lambda ele: ele[k1][k2][k3], reverse = rev)
My question is if there is any way to express this more succinctly. (note, reverse
references the [unshown] variable rev
, so I figured there must be a way to do the same with ele
)
CodePudding user response:
This can be implemented with closures:
def nested_itemgetter(keys):
def getter(val):
for key in keys:
val = val[key]
return val
return getter
Or class:
class NestedItemGetter:
def __init__(self, keys):
self.keys = keys
def __call__(self, val):
for key in self.keys:
val = val[key]
return val
Usage:
list_of_dict = sorted(list_of_dict, key=nested_itemgetter(keys), reverse=rev)
list_of_dict = sorted(list_of_dict, key=NestedItemGetter(keys), reverse=rev)
CodePudding user response:
Try:
from functools import partial
def nested_itemgetter(ks, d):
res = d
for key in ks:
res = res[key]
return res
rev = True
list_of_dict = [{"a": {"b": {"c": 1}}}, {"a": {"b": {"c": 2}}}, {"a": {"b": {"c": 3}}}]
keys = ["a", "b", "c"]
res = sorted(list_of_dict, key=partial(nested_itemgetter, keys), reverse=rev)
print(res)
Output
[{'a': {'b': {'c': 3}}}, {'a': {'b': {'c': 2}}}, {'a': {'b': {'c': 1}}}]