Reputation: 9522
Let's say I have a list of items I want to sort: items = [ item1, item2, item3 ]
. The attribute I want to use to sort them is item.data.value
, so I'd normally go:
sorted(items, key=attrgetter('data.value'))
And that'd work just fine. However, data
can actually be None
so obviously I couldn't access value
.
How do you usually deal with scenarios like this?
PS: neither this question nor this one helped.
Upvotes: 7
Views: 3701
Reputation: 374
attrgetter with default value support.
behaves like dictionary.get()
D.get(k[,d]) -> D[k] if k in D, else d
d defaults to None. detailed info: groups.google.com:python-ideas
Upvotes: -1
Reputation: 4260
Just filter the None values first before sending them to sorted.
sorted(filter(None, items), key=attrgetter('data.value'))
And if you really want the None items too, you can do something like this:
# items already defined with values
new_items_list = sorted(filter(None, items), key=attrgetter('data.value'))
new_items_list.extend([None] * (len(items) - len(new_items_list)))
However, I am not sure whether you really need the None items.
EDIT: Fixed the end code which will retain the None items.
Upvotes: 0
Reputation: 31270
Use as key a tuple, like (False, value)
. If value is None, then the tuple should be (True, None)
.
Tuples are compared by their first element first, then the second, et cetera. False sorts before True. So all None values will be sorted to the end.
def none_to_end_key(item):
value = item.data.value if item.data else None
return (value is None, value)
sorted(items, key=none_to_end_key)
Will sort all None values to the end.
I see now that you have tagged your question Python-2.7, then this is probably overkill. In Python 3, comparing None to an integer or string raises an exception, so you can't simply sort a list with None and other values, and something like this is needed.
Upvotes: 3
Reputation: 7797
sorted(items, key=lambda i: i.data.value if i.data else 0)
Upvotes: 7
Reputation: 12610
If you do not have a function handy that returns the key you want then just write your own.
def item_key(item):
try:
return item.data.value
except AttributeError:
return None
sorted(items, key=item_key)
Upvotes: 0
Reputation: 560
just filter for the None before sorting
sorted(filter(None, items), key=attrgetter('data.value'))
Upvotes: 2