Having trouble wrapping my head around how to order this list which consists of nested defaultdicts. I was able to sort by 'registration' key and the 'classes' value with this;
sorted(dict1.items(), key=itemgetter(1), reverse=True)
Which produced;
[('registration', {'count': 11, 'classes': Counter({'class1': 5, 'class2': 5, 'class3': 1}), 'date': defaultdict(<function date_record at 0x7fc173646500>, {datetime.date(2016, 6, 7): {'count': 1, 'hour': Counter({16: 1})}, datetime.date(2016, 6, 6): {'count': 10, 'hour': Counter({16: 5, 14: 2, 8: 1, 10: 1, 12: 1})}})})]
However now I'm trying to sort by 'date' which is a nested defaultdict. I'm trying to order by the date chronologically (from - to) and then finally, order the 'hour' Counter() chronologically (for reference; 8 = 8am, and 16 = 4pm).
So the above defaultdict should look like this;
[('registration', {'count': 11, 'classes': Counter({'class1': 5, 'class2': 5, 'class3': 1}), 'date': defaultdict(<function date_record at 0x7fc173646500>, {datetime.date(2016, 6, 6): {'count': 10, 'hour': Counter({16: 5, 14: 2, 12: 1, 10: 1, 8: 1})}, datetime.date(2016, 6, 7): {'count': 1, 'hour': Counter({16: 1, 14: 4})}})})]
I'm just having trouble figuring out how to access the defaultdict. Any guidance on how I can access it within a sort?
The key
parameter to sort or sorted can be any callable. This callable should return objects taht are directly comparable with Python's ==
and <=
operators. There is no need for the object passed as key
to be the callable returned by itemgetter
or some other complicated construct.
There is no need for it to be a short - one expression function - that can be in a lambda as well.
So, just define a function, let it have the size it has to - to retrieve the attributes you want to compare on. If there are more than one value, return a sequence with those values. Pass this function on the key
named parameter to sort
.
I am not certain if I can figure out how you ant to order your keys/values inside your date
nested dir, but it could be something along:
def sort_key(item):
dates = list(item["date"].items())
# the key in the lambda bellow will get
# tuples with the datetime and subdictionary for each date:
dates.sort(key=lambda inner_date: (inner_date[0], sorted(inner_date[1]["hour"].keys())
return dates
Note that you need the inner sorting in rder to have your keys respecting the "hour" values as well - I did that by making each key on the sort of each "date" of each of your list items return a tuple where the first element is the "date" itself used as key, the second, a sorted list of the values showing up in the counter (but not the count for each value) .
If this secondary key is too complex to fit in a lambda, just create another function for it. These functions will only be called once for each item in the outer list you are sorting, so your performance should still be ok.