Reputation: 2163
How can I sort an array by a given set of indexes and prioritize the value being in that index. As of now, I can not get the sort methods to sort by a specific index throughout the entire array because 0 value causes issues.
For example, first sort by index 1, then by index 0, then 2
tmpList = [[0,-10,0],[0,10,0],[0,5,0],[1,0,0],[0,0,-1],[0,0,0],[0,0,5]]
Res = sorted(tmpList, key=lambda x: x[1] )
>>[[0, -10, 0], [1, 0, 0], [0, 0, -1], [0, 0, 0], [0, 0, 5], [0, 5, 0], [0, 10, 0]]
I need more flexibility in this sorting, so that I can prioritize a value other than zero being in the index as priority, so it would sort as:
[[0,-10,0],[0,5,0],[0,10,0],[1,0,0],[0,0,-1],[0,0,5],[0,0,0]]
How to sort in python with multiple conditions? has a similar task, but the zero problem remains
Upvotes: 4
Views: 25358
Reputation: 21893
When sorting by multiple conditions, you should always use tuple
s.
The Python's built-in sorted()
will sort the list by comparing the first values in the tuples, if they're equal then the second values, if they're also equal then the third ones, etc.
Example: sorted([(0, 5, 1), (1, 3, 4), (0, -3, 1), (1, 3, 5)])
will output
(0, -3, 1),
(0, 5, 1),
(1, 3, 4),
(1, 3, 5)
If you wish for the sort to happen in a custom order, in your case index 1
having priority over index 0
, you can do that by providing a lambda function that simply re-arranges these tuples:
>>> l = [(0, 5, 1), (1, 3, 4), (0, -3, 1), (1, 3, 5)]
>>> sorter = lambda x: (x[1], x[0], x[2])
>>> sorted_l = sorted(l, key=sorter)
This will output:
(0, -3, 1),
(1, 3, 4),
(1, 3, 5),
(0, 5, 1)
Now if you want the elements with 0
at index 1 (x[1] == 0
) to be the last, you must add this condition to the beginning of the tuple returned by the sorter
function:
sorter = lambda x: (x[1] == 0, x[1], x[0], x[2])
That's the exact same as before, but with x[1] == 0
added to the beginning. This comparison will yield either True
or False
, and since False
is represented as 0
and True
is represented as 1
, we can deduce that False < True
when sorting, thus those elements where x[1] != 0
will be first. Essentially this sorts those elements with a beginning 0
to the very end. You can repeat this for x[0] == 0
and x[2] == 0
too, so your final version would then be: sorted(tmpList, key=lambda x: (x[1] == 0, x[1], x[0] == 0, x[0], x[2] == 0, x[2]))
Upvotes: 14