0

For example, I have a list:

[12, 1205, 102, 6]

I want to get

[1, 3, 2, 0]

Because this is the position they are supposed to be in if the list is sorted.

How can I achieve this in python?

4
  • 2
    Did you try to solve this? Do you have any code that you need help with? Commented Aug 14, 2021 at 20:10
  • 1
    Can't you just subtract everything by 1? Commented Aug 14, 2021 at 20:11
  • I am just looking for a way to finish it in one line, I wish not to use for loop or while loop Commented Aug 14, 2021 at 20:12
  • May be I should change an example Commented Aug 14, 2021 at 20:13

3 Answers 3

2

Use a double numpy.argsort, or self-indexing:

l = [12, 1205, 102, 6]

out = np.argsort(np.argsort(l)).to_list()

# or
x = np.argsort(l)
out = x[x]

Output: [1, 3, 2, 0]

older (inefficient) answer

IIUC, you want the sorted rank:

sorted_list = sorted(your_list)
[sorted_list.index(x) for x in your_list]
Sign up to request clarification or add additional context in comments.

4 Comments

Although this answers the question, this one-liner is incredibly inefficient, you are sorting the list N times (being N the length of the list).
That's very true, I computed the sorted values outside of the comprehension
Note that this solution will not work for lists that contain duplicate values. Also, the sequential search for each element gives it an O(N x NLogN) time complexity. But O(N + NlogN) could be achieved.
@AlainT. yes that's correct, this was not a good approach, I added a better alternative
1

You can get a list of indexes in the order of sorted values using the sorted() function, then use this to set the positions in the resulting list:

L = [12, 1205, 102, 6]

P = sorted(range(len(L)),key=L.__getitem__) # positions in sorted order
S = [None]*len(L)                           # resulting list
for p,i in enumerate(P): S[i]=p             # assign position at original indexes 

print(S) # [1, 3, 2, 0]

The equivalent solution using numpy could look like this:

S = np.zeros(len(L),dtype=np.int)     # prepare resulting array
S[np.argsort(L)] = np.arange(len(L))  # assign positions at indexes
 
print(S) # array([1, 3, 2, 0])

2 Comments

I think this is correct, but I don't see why you have to create the S array, instead of just using a list comprehension for clarity
Because, in order to place p values at the appropriate index in S using a comprehension (i.e. appending), I would need to sort P a second time. I you print i and p inside the for loop, you will see that the assignments are not performed in sequential order.
0

Sorting your list can be done with numpy:

numpy.argsort([2, 3, 5, 1, 4])

3 Comments

This is not what OP expected, this gives the indexes to take in order to sort the array.
Uh ok well sorry then. But could you explain me how is this different? I'm lost and would appreciate learning the difference between argsort and the OP's expectation
You have the index to take to get the sorted array, OP simply wanted the rank.

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.