0

Following up on this question: Sort when values are None or empty strings python I am looking for a fully working solution in Python 3.

In Python 2.7.6, I can successfully do the following:

> list_with_none = [(1,"foo"), (2,"bar"), (3,""), (4,None), (5,"blub")]
> col = 1
> sorted(list_with_none, key=lambda k: (k[col] is None, k[col] == "", k[col]))
[(2, 'bar'), (5, 'blub'), (1, 'foo'), (3, ''), (4, None)]
> sorted(list_with_none, key=lambda k: (k[col], k[col] is None, k[col] == ""), reverse=True)
[(1, 'foo'), (5, 'blub'), (2, 'bar'), (3, ''), (4, None)]

In Python 3.4.3, I can't find a working solution for reverse sorting, which puts empty strings and None values at the end of the list (which is what I explicitly need):

> list_with_none = [(1,"foo"), (2,"bar"), (3,""), (4,None), (5,"blub")]
> col = 1
> sorted(list_with_none, key=lambda k: (k[col] is None, k[col] == "", k[col])) 
[(2, 'bar'), (5, 'blub'), (1, 'foo'), (3, ''), (4, None)]
> sorted(list_with_none, key=lambda k: (k[col], k[col] is None, k[col] == ""), reverse=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: NoneType() < str()
Community
  • 1
  • 1
s-m-e
  • 3,433
  • 2
  • 34
  • 71

2 Answers2

2

When passing reverse=True, invert the checks for None and the empty string:

sorted(list_with_none, key=lambda k: (k[col] is not None, k[col] != "", k[col]), reverse=True) 

This works in Python 2 as well as Python 3.

orlp
  • 112,504
  • 36
  • 218
  • 315
1

All you care about is if the value is None or not None so there are only two conditions that matter

print(sorted(list_with_none, key=lambda x: (x[1] is not None, x[1]), reverse=True))
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321