pythonpython-3.xordereddictionaryordereddict

How to reorder a python OrderedDict using cascading list values


I've seen simpler examples of this but I'm trying to get a bit more complex and can't work it out.

If I have an OrderedDict in which the key describes a person and the value is a list of their [age, gender, hairColor].

from collections import OrderedDict
myOD = OrderedDict(adultMale1=[50, 'male', 'grey'], babyFemale=[1, 'female', 'red'], teenMale=[13, 'male', 'blonde'], teenFemale=[13, 'female', 'red'], adultMale2=[50, 'male', 'blonde'])
print myOD.keys()
# Result: myOD:  ['teenMale', 'babyFemale', 'adultMale2', 'teenFemale', 'adultMale1']

What I want is to sort the OrderedDict first by age, then by gender, and then by hairColor. This would then be the correct result I'm looking for.

# Result: ['babyFemale', 'teenFemale', 'teenMale', 'adultMale2', 'adultMale1']

I have figured out a way to sort by age.

sortAgeList = []
for v in myOD.values():
    sortAgeList.append(v[0])
sortAgeList.sort()

myNewOD = OrderedDict()
for age in sortAgeList:
    for key, value in myOD.items():
        if value[0] == age:
            myNewOD[key] = myOD[key]
print 'myNewOD: ', myNewOD.keys()  
# Result: myNewOD:  ['babyFemale', 'teenMale', 'teenFemale', 'adultMale2', 'adultMale1']

However, I've tried multiple ways to extrapolate this approach to then re-sort any tie-breakers that are the same age and then again any tie-breakers that are the same gender, but it's getting really complex and I keep thinking there must be a simpler way.

I'm hoping someone out there has an idea to help me out. Thank you all in advance.


Solution

  • The default sort order is already lexicographic.

    >>> sorted(myOD, key=myOD.get)
    ['babyFemale', 'teenFemale', 'teenMale', 'adultMale2', 'adultMale1']
    

    Therefore:

    >>> from operator import itemgetter
    >>> OrderedDict(sorted(myOD.items(), key=itemgetter(1)))
    OrderedDict([('babyFemale', [1, 'female', 'red']),
                 ('teenFemale', [13, 'female', 'red']),
                 ('teenMale', [13, 'male', 'blonde']),
                 ('adultMale2', [50, 'male', 'blonde']),
                 ('adultMale1', [50, 'male', 'grey'])])