8

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 (numerically). 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'},
]
Paul Floyd
  • 5,530
  • 5
  • 29
  • 43
mluebke
  • 8,588
  • 7
  • 35
  • 31

4 Answers4

23
mylist.sort(key=lambda d: (d['weight'], d['factor']))

or

import operator
mylist.sort(key=operator.itemgetter('weight', 'factor'))
dF.
  • 74,139
  • 30
  • 130
  • 136
  • 4
    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 May 14 '09 at 02:01
  • 2
    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. – Esteban Küber May 14 '09 at 02:12
  • 2
    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 May 14 '09 at 02:41
  • 3
    Not showing people lambda who haven't learned lambda helps ensure they'll never learn it. – Bluu May 14 '09 at 05:04
  • +1 because it showed me operator.itemgetter() (and I'm not afraid of lambda, btw) – FlipMcF Jan 17 '13 at 19:44
1

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
  • 46,881
  • 3
  • 27
  • 21
1

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
  • 8,588
  • 7
  • 35
  • 31
-1
decoratedlist = [(item[weight], item) for item in mylist]
decoratedlist.sort()
results = [item for (key, item) in decoratedlist]
user106514
  • 161
  • 6
  • 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. – Paweł Polewicz May 14 '09 at 22:24
  • 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. – user106514 May 15 '09 at 16:19