I want to sort the positive values in a list of numbers, but leave the negative values where they are.
I tried to create a custom comparison function that says that negative numbers are equal to any other number, but this does not seem to work as I expected. Here is the code:
import functools
def my_cmp(a, b):
if (a < 0) or (b < 0):
return 0
elif a < b:
return -1
else:
return 1
x = [2, 7, 5.2, -7, -2, 10, 30, 13.1, -3, 14, 9, 15]
print(sorted(x, key=functools.cmp_to_key(my_cmp)))
The code returns:
[2, 5.2, 7, -7, -2, 9, 10, 13.1, 14, 30, -3, 15]
But I expected
[2, 5.2, 7, -7, -2, 10, 13.1, 30, -3, 9, 14, 15]
since Python's sort is supposed to be stable. Is this not working because the negative numbers are equal to any other number?
Is there a better way to this without using loops? I can do this by breaking up the list and sorting each part corresponding to the positive numbers, but I would like a more elegant way to this.
Splitting the list into discrete parts based on sign and sorting those is probably easiest. Here's a way using itertools.groupby
from itertools import chain, groupby
x = [2, 7, 5.2, -7, -2, 10, 30, 13.1, -3, 14, 9, 15]
groups = groupby(x, key=lambda a: a > 0)
res = list(chain.from_iterable(sorted(g) if k else g for k, g in groups))
print(res)
# [2, 5.2, 7, -7, -2, 10, 13.1, 30, -3, 9, 14, 15]