user-2147482637
user-2147482637

Reputation: 2163

Python sort array of arrays by multiple conditions

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

Answers (1)

Mahi
Mahi

Reputation: 21893

When sorting by multiple conditions, you should always use tuples. 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

Related Questions