4

I am trying to sort a list, move all 0 to the end of list. example: [0,1,0,2,3,0,4]->[1,2,3,4,0,0,0]

and I see someone code it in 1 line

list.sort(cmp=lambda a,b:-1 if b==0 else 0)

But I don't understand what inside the parentheses mean.

Could anyone tell me? Thank you.

yoppy
  • 83
  • 1
  • 1
  • 5
  • 2
    How much do you understand, how much don't you understand? Do you know what the `cmp` parameter does? Do you know what a `lambda` is? Do you know what the inline `if..else` is? – deceze Dec 08 '15 at 15:18
  • try googling your tags: `python`, `lambda`, `sort` and you 'll find how to use them and what they do. – linluk Dec 08 '15 at 15:22
  • 1
    Even if you know Python, you might miss the fact that this line depends on an *implementation detail* about the order in which the items are compared, so I do think that the question is on topic. – kay Dec 08 '15 at 15:35

2 Answers2

14

Preface:

Sort a list according to the normal comparison:

some_list.sort()   

Supply a custom comparator:

some_list.sort(cmp=my_comparator)

A lambda function:

x = lambda a, b: a - b
# is roughly the same as
def x(a, b):
    return a - b

An if-else-expression:

value = truthy_case if condition else otherwise
# is roughly the same as
if condition:
    value = truthy_case
else:
    value = otherwise

The line list.sort(cmp=lambda a,b:-1 if b==0 else 0) itself:

Now, the condition in the comparator is whether b==0, if so indicate that b has a bigger value than a (the sign of the result is negative), otherwise indicate that the values compare the same (the sign is zero).

Whilst Python's list.sort() is stable, this code is not sane, because the comparator needs to test a, too, not only b. A proper implementation would use the key argument:

some_list.sort(key=lambda a: 0 if a == 0 else -1)

Fixed list.sort(cmp=...) implementation:

If you want to use list.sort(cmp=...) (you don't) or if you are just curious, this is a sane implementation:

some_list.sort(cmp=lambda a, b: 0 if a == b else
                               +1 if a == 0 else
                               -1 if b == 0 else 0)

But notice:

In Py3.0, the cmp parameter was removed entirely (as part of a larger effort to simplify and unify the language, eliminating the conflict between rich comparisons and the __cmp__ methods).

An alternative:

Sorting a list is in O( log ). I do not know if for this simple problem the code runs faster, but I wouldn't think so. An O() solution is filtering:

new_list = [x for x in some_list if x != 0]
new_list.extend([0] * (len(some_list) - len(new_list)))

The difference will probably only matter for quite long lists, though.

Community
  • 1
  • 1
kay
  • 23,543
  • 10
  • 89
  • 128
0
>>> sorted(l, key=lambda x:str(x) if x == 0 else x)
[1, 3, 4, 8, 0, 0, 0]

Guess what's happening here? I am exploiting the fact that, as a preference, python will pick up integers first, then strings. SO I converted 0 into '0'.

Here's the proof.

>>> ll = [3,2,3, '1', '3', '0']
>>> sorted(ll)
[2, 3, 3, '0', '1', '3']
Arindam Roychowdhury
  • 3,975
  • 5
  • 43
  • 52