views:

284

answers:

4

I've got a python list of dictionaries:

mylist = [
{'id':0, 'weight':10, 'factor':1, 'meta':'ABC'},
{'id':1, 'weight':5, 'factor':1, 'meta':'ABC'},
{'id':2, 'weight':5, 'factor':2, 'meta':'ABC'},
{'id':3, 'weight':1, 'factor':1, 'meta':'ABC'}
]

Whats the most efficient/cleanest way to order that list by weight then factor (numericaly). The resulting list should look like:

mylist = [
{'id':3, 'weight':1, 'factor':1, 'meta':'ABC'},
{'id':1, 'weight':5, 'factor':1, 'meta':'ABC'},
{'id':2, 'weight':5, 'factor':2, 'meta':'ABC'},
{'id':0, 'weight':10, 'factor':1, 'meta':'ABC'},
]
+1  A: 

Something along the lines of the following ought to work:

def cmp_dict(x, y):
    weight_diff = y['weight'] - x['weight']
    if weight_diff == 0:
        return y['factor'] - x['factor']
    else:
        return weight_diff

myList.sort(cmp_dict)
Greg Case
+18  A: 
mylist.sort(key=lambda d: (d['weight'], d['factor']))

or

import operator
mylist.sort(key=operator.itemgetter('weight', 'factor'))
dF
I'd love to +1 this because it uses key. I can't +1 anything with a lambda. A def version is usually easier for n00bz than a lambda.
S.Lott
+1 because it uses key and I'm not afraid of lambda ;-)
Rick Copeland
That a n00b can't understand a lambda doesn't mean it shouldn't be used. Actually, lambdas make code easier to follow and allow some magic/sugar impossible in other ways. If you don't understand lambdas, you should go searching for questions like this http://stackoverflow.com/questions/150129/what-is-a-lambda or www.diveintopython.org/power_of_introspection/lambda_functions.html and come back when you understand them.Also, http://stackoverflow.com/questions/134626/which-is-more-preferable-to-use-in-python-lambda-functions-or-nested-functions discuses *when* you should use lambdas.
voyager
It isn't a question of understanding or fear. I get tired of n00b questions. A simple `def` does the same thing in a way that is generally easier to follow and understand. After 30 years, I've learned that all software is maintained and "enhanced" by n00bz who don't get the nuances.
S.Lott
Not showing people lambda who haven't learned lambda helps ensure they'll never learn it.
Bluu
+1  A: 

I accepted dF's answer for the inspiration, but here is what I ultimately settled on for my scenario:

@staticmethod
def ordered_list(mylist):
    def sort_func(d):
        return (d['weight'], d['factor'])

    mylist.sort(key=sort_func)
mluebke
'operator.itemgetter('weight', 'factor')' is the pythonic way to express your 'sort_func'.
John Fouhy
A: 
decoratedlist = [(item[weight], item) for item in mylist]
decoratedlist.sort()
results = [item for (key, item) in decoratedlist]
This doesn't work (did You mean "item['weight']"?). Also, when fixed, it works in cPython because of a bit of luck, but doesn't have to work in other Python implementations. The tuple should have 3 elements. Also You rewrite the list when You don't have to, look on the accepted answer.
Reef
did you mean item['weight']? yes, I did; when I used the snippet I got the key from a variable, hence the error. btw, it works in py2.4.4, 2.5.1, 2.5.2.