0

There is a list like

l = [{"n": 1, "m": 3}, {"n": None, "m": 1}, {"n": 3, "m": None}, {"n": None, "m": 0}]

And I want to order it by one specified key, n for example. Besides, some value of the key may be None, and I want to leave them at behind

Here's my trial

l = [{"n": 1, "m": 3}, {"n": None, "m": 1}, {"n": 3, "m": None}, {"n": None, "m": 0}]

from functools import partial
def order(key, item):
    if item[key]:
        return item[key]
    else:
        return 0
order_key = "n"
r = sorted(l, key=partial(order, order_key), reverse=True)
print(r)

Is there a better way to make it happen?

Georgy
  • 12,464
  • 7
  • 65
  • 73
jia Jimmy
  • 1,693
  • 2
  • 18
  • 38

3 Answers3

4

Here's one approach using sorted with a key:

sorted(l, key=lambda x: -x['n'] if x['n'] is not None else float('inf'))

[{'n': 3, 'm': None},
 {'n': 1, 'm': 3},
 {'n': None, 'm': 1},
 {'n': None, 'm': 0}]

Let's check with another example:

l = [ {"n":1, "m":3}, {"n":None, "m":1}, {"n":3, "m":None}, {"n":None, "m":0}, 
      {"n":0, "m":0}, {"n":-1, "m":0}]

sorted(l, key=lambda x: -x['n'] if x['n'] is not None else float('inf'))

[{'n': 3, 'm': None},
 {'n': 1, 'm': 3},
 {'n': 0, 'm': 0},
 {'n': -1, 'm': 0},
 {'n': None, 'm': 1},
 {'n': None, 'm': 0}]
yatu
  • 86,083
  • 12
  • 84
  • 139
2

use a key function that returns a tuple for a double criteria:

l = [ {"n":1, "m":3}, {"n":None, "m":1}, {"n":3, "m":None}, {"n":None, "m":0}]

result = sorted(l,key = lambda d : (d["m"] is None,d["m"] or 0))

result:

>>> result
[{'m': 0, 'n': None},
 {'m': 1, 'n': None},
 {'m': 3, 'n': 1},
 {'m': None, 'n': 3}]

Let's clarify how and why it works:

(d["m"] is None,d["m"] or 0) is a tuple:

  • True if the value is None for the first element, which guarantees that None entries are last (negate for the reverse effect)
  • the other one is the tiebreaker, with the or trick to convert None to 0 so it's comparable with other integers without errors (although here it is not needed since first boolean stops the tuple comparison so we could write (d["m"] is None,d["m"]))
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
1
l = [ {"n":1, "m":3}, {"n":None, "m":1}, {"n":3, "m":None}, {"n":None, "m":0}]
newlist = sorted(l, key=lambda k:  (k['n'] is None, k['n'] == 0, k['n']), reverse = True)
print (newlist)

output:

[{'n': None, 'm': 1}, {'n': None, 'm': 0}, {'n': 3, 'm': None}, {'n': 1, 'm': 3}]
ncica
  • 7,015
  • 1
  • 15
  • 37