views:

540

answers:

4

Ok, here's what I'm trying to do... I know that itemgetter() sort could to alphabetical sort easy, but if I have something like this:

[{'Name':'TOTAL', 'Rank':100}, {'Name':'Woo Company', 'Rank':15}, {'Name':'ABC Company', 'Rank':20}]

And I want it sorted alphabetically (by Name) + include the condition that the one with Name:'TOTAL' should be listed last in the sequence, like this:

[{'Name':'ABC Company', 'Rank':20}, {'Name':'Woo Company', 'Rank':15}, {'Name':'TOTAL', 'Rank':100}]

How would I do that?

+1  A: 

Use the key parameter of sort or sorted.

For example:

dicts = [
     {'Name':'TOTAL', 'Rank':100}, 
     {'Name':'Woo Company', 'Rank':15},
     {'Name':'ABC Company', 'Rank':20}
]

def total_last(d):
    if d['Name'] == 'TOTAL':
     return '\xff\xff\xff\xff\xff\xff'
    return d['Name'].lower()

import pprint
pprint.pprint(sorted(dicts, key = total_last))

>python sort_dict.py
[{'Name': 'ABC Company', 'Rank': 20},
 {'Name': 'Woo Company', 'Rank': 15},
 {'Name': 'TOTAL', 'Rank': 100}]
Aaron Maenpaa
+1 that's what I would have suggested.
Nadia Alramli
+1: Very clear with no lambda. However, "sort_key" is an unwise choice of names. `total_last` might be a more descriptive name for the key function.
S.Lott
@S.Lott You're right about the name.
Aaron Maenpaa
+7  A: 

The best approach here is to decorate the sort key... Python will sort a tuple by the tuple components in order, so build a tuple key with your sorting criteria:

sorted(list_of_dicts, key=lambda d: (d['Name'] == 'TOTAL', d['Name'].lower()))

This results in a sort key of:

  • (True, 'total') for {'Name': 'TOTAL', 'Rank': 100}
  • (False, 'woo company') for {'Name': 'Woo Company', 'Rank': 15}
  • (False, 'abc company') for {'Name': 'ABC Company', 'Rank': 20}

Since False sorts earlier than True, the ones whose names aren't TOTAL will end up together, then be sorted alphabetically, and TOTAL will end up at the end.

Jarret Hardie
wow, that was pretty slick... I like that, as it doesn't require creating a custom sorting algorithm either outside of that sorted() declaration.Thank you!
Crazy Serb
+1  A: 
>>> lst = [{'Name':'TOTAL', 'Rank':100}, {'Name':'Woo Company', 'Rank':15}, {'Name':'ABC Company', 'Rank':20}]
>>> lst.sort(key=lambda d: (d['Name']=='TOTAL',d['Name'].lower()))
>>> print lst
[{'Name': 'ABC Company', 'Rank': 20}, {'Name': 'Woo Company', 'Rank': 15}, {'Name': 'TOTAL', 'Rank': 100}]
Dave
A: 

Well, I would sort it in multiple passes, using list's sort method.

list = [{'Name':'TOTAL', 'Rank':100}, {'Name':'Woo Company', 'Rank':15}, {'Name':'ABC Company', 'Rank':20}]

list.sort(key = lambda x: x['Name']) # Sorted by Name, alphabetically

list.sort(key = lambda x: 'b' if x['Name'] == 'TOTAL' else 'a')
Mike Hordecki