4

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

16
  • 1
    "first sort by index 1, then by index 0, then 2" does not produce your desired output. Commented Aug 11, 2015 at 12:52
  • to me it does, if the condition is non-zero Commented Aug 11, 2015 at 12:53
  • 1
    @user1938107 Why is [0, 0, 0] before [0, 0, -1]? Commented Aug 11, 2015 at 12:58
  • 1
    Why is [0,0,0] before anything? Commented Aug 11, 2015 at 12:59
  • 1
    @user1938107 That's the only logic you told us; fix your question with proper examples and explanations, and we shall then answer your question properly. Commented Aug 11, 2015 at 13:04

1 Answer 1

14

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]))

Sign up to request clarification or add additional context in comments.

9 Comments

I don't think this is doing what I am describing, I get [0, -10, 0], [0, 0, -1], [0, 0, 0] as the first 3
@user1938107 Your "desired output" doesn't match with what you told us. My solution works for the "first sort by index 1, then by index 0, then 2".
Your solution does not prioritize non-zero elements.
"so that I can prioritize a value other than zero", also, your solution is what I link to in the question
@user x[1] == 0 is just a comparison which returns True or False. When sorting, False < True. Thus (False, 1) gets sorted before (True, 1)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.