Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Sort a list of objects based on their attributes

Just to preface this, I've already checked out posts pertaining to this question and they haven't fully answered mine.

So I would just like to know how to sort a list of objects based on their attributes in two ways:

  1. if the attribute is a string (to alphabetize)
  2. if the attribute is a integer (to do by numerical order)

This is my list of classes:

mainList = [
    hero( name='SirGoose', classes='Fighter', level=150 ),
    hero( name='Conan', classes='Barbarian', level=160 ),
    hero( name='KingArthur', classes='Knight', level=170 )
]

So what I'm really looking for is a way to sort this list to that the hero's names are sorted in alphabetical order, then another method for level. Thank you!

like image 347
SirGoose Avatar asked Oct 11 '14 02:10

SirGoose


1 Answers

sorted, list.sort accept optional key parameter. Pass a key function. The return value of the function is used for comparison instead of the original value:

>>> from collections import namedtuple
>>> hero = namedtuple('hero', ['name', 'classes', 'level'])
>>>
>>> mainList = [
...     hero(name='SirGoose', classes='Fighter', level=150 ),
...     hero(name='Conan', classes='Barbarian', level=160 ),
...     hero( name='KingArthur', classes='Knight', level=170 )
... ]
>>> sorted(mainList, key=lambda h: (h.name, h.level))
[hero(name='Conan', classes='Barbarian', level=160),
 hero(name='KingArthur', classes='Knight', level=170),
 hero(name='SirGoose', classes='Fighter', level=150)]

NOTE: the key function used here (lambda) returns a tuple. tuples are compared item by item. If the first items are same, the next items are compared, ...

>>> ('SirGoose', 12) < ('Barbarian', 160)
False
>>> ('SirGoose', 12) < ('SirGoose', 160)
True

Alternative using operator.attrgetter:

>>> import operator
>>> sorted(mainList, key=operator.attrgetter('name', 'level'))
[hero(name='Conan', classes='Barbarian', level=160),
 hero(name='KingArthur', classes='Knight', level=170),
 hero(name='SirGoose', classes='Fighter', level=150)]
like image 109
falsetru Avatar answered Nov 12 '22 05:11

falsetru