How do I sort a list of integers based on their absolute values such that the positive number gets a higher precedence -
Sample Input
lst = [1, -3, 3, -3, 12, 10]
Expected Output
[1, 3, -3, -3, 10, 12]
I am able to do it right now with a code like this, but I am bothered by that arbitrary 0.1
in the function and wonder if there is a cleaner way
My code
sorted(lst, key=lambda x: abs(x) if x >= 0 else abs(x) 0.1)
# [1, 3, -3, -3, 10, 12]
CodePudding user response:
Another solution is having a tuple as a sorting key:
sorted(lst, key=lambda x: (abs(x), x < 0))
To understand it better:
1 ~ (1, False) ~ (1, 0)
-3 ~ (3, True) ~ (3, 1)
3 ~ (3, False) ~ (3, 0)
-3 ~ (3, True) ~ (3, 1)
12 ~ (12, False) ~ (12, 0)
10 ~ (10, False) ~ (10, 0)
CodePudding user response:
Create a custom comparator function which returns a tuple of size 2. The first value of the tuple is for absolute value and the second value is for ordering negative and positive values with the same absolute value.
sorted(lst, key=lambda x: (abs(x), -x))
# [1, 3, -3, -3, 10, 12]
For each value in the list values compared would be:
1 -> (1, -1)
3 -> (3, -3)
-3 -> (3, 3)
10 -> (10, -10)
12 -> (12, -12)
This way positive values are pushed to the beginning and negatives values to the end in each group.
CodePudding user response:
I'm quite confident that two simple sorts will be more efficient here than one more complex sort.
lst.sort(reverse=True)
lst.sort(key=abs)
Btw yours would be a bit shorter and faster (90 ms and 210 us in my benchmarks) without the unnecessary abs
(you already know the sign):
sorted(lst, key=lambda x: x if x >= 0 else 0.5 - x)
Benchmark results with 100,000 random integers from -100,000 to 100,000 (Try it online!):
True 95 ms original
True 42 ms Kelly
True 128 ms Yevhen
True 133 ms Ch3ster
True 95 ms original
True 42 ms Kelly
True 121 ms Yevhen
True 132 ms Ch3ster
True 97 ms original
True 42 ms Kelly
True 119 ms Yevhen
True 129 ms Ch3ster
Benchmark with 500 numbers from -500 to 500, since you just commented your lists are "few 100 elements long" (Try it online!):
True 233 us original
True 85 us Kelly
True 192 us Yevhen
True 198 us Ch3ster
True 231 us original
True 83 us Kelly
True 192 us Yevhen
True 195 us Ch3ster
True 229 us original
True 87 us Kelly
True 194 us Yevhen
True 196 us Ch3ster