Say I have a list [102, 97, 116, 101]
, and I want to rank their values numerically while retaining the value's position in the list, as in [3, 1, 4, 2]
. How would I go about this?
Asked
Active
Viewed 94 times
1

John
- 19
- 2
-
Are the numbers in the input list all unique? – Hubert Grzeskowiak Oct 24 '17 at 03:13
-
The numbers are generated from the ASCII values of characters from a string (English word, alphabetic only). So the list can be a range of values, as well as have duplicate values. If two numbers are the same (ie: `[51, 35, 51]` they will be ordered `[1, 2, 3]`). So they are unique in that respect. – John Oct 24 '17 at 03:19
3 Answers
3
Sort an input of indices keyed on a lookup into your existing list
:
>>> mylist = [102, 97, 116, 101]
>>> ranks = sorted(range(1, len(mylist)+1), key=lambda i: mylist[i-1], reverse=True)
>>> print(ranks)
[3, 1, 4, 2]
The use of i-1
as the index is because you used 1-up ranks (while Python uses 0-up indices).

ShadowRanger
- 143,180
- 12
- 188
- 271
-
1If you want the element as well as the rank, use `enumerate` instead: `sorted(enumerate([102, 97, 116, 101], 1), key=lambda x: x[1], reverse=True)` – cs95 Oct 24 '17 at 03:18
-
This can be simplified by using `0` as index and only adding `1` to the result of the lambda function. – Hubert Grzeskowiak Oct 24 '17 at 03:33
-
@HubertGrzeskowiak: Huh? The result of the `lambda` is the key value; adding one to it makes no sense. The OP's intended output is 1-up, so you need to add one to the results from `sorted` (not the `lambda`) if you use 0-up indices without subtraction (which would let you use `key=mylist.__getitem__` for a slight speed boost). – ShadowRanger Oct 24 '17 at 03:35
0
Here's a possible way for lists of unique numbers:
- Create a copy of the list and sort it (reversed). Call it
sorted_list
- Create a third, empty list
result
- Go through the input list and find the index of each number in the
sorted_list
list. - Append that index to the
result
list.
Given your example data that would result in:
input_list = [102, 97, 116, 101]
sorted_list = [97, 101, 102, 116]
result = [1, 3, 0, 2]
Add 1
to the indices if you want the result to start at 1
instead of 0
.
Implementation:
input_list = [102, 97, 116, 101]
sorted_list = sorted(input_list, reverse=True)
result = []
for n in input_list:
result.append(sorted_list.index(n))
# result now contains [1, 3, 0, 2]

Hubert Grzeskowiak
- 15,137
- 5
- 57
- 74
-
-
@ReblochonMasque correct. Hence my comment on the question. – Hubert Grzeskowiak Oct 24 '17 at 03:17
-
1Please don't name-shadow built-ins; you've done it twice here, for `input` and `sorted`. – ShadowRanger Oct 24 '17 at 03:18
-
0
We can sort and grab the index of item in the unsorted list:
sorted_list = sorted([102, 97, 116, 101])
[sorted_list.index(e) for i, e in enumerate([102, 97, 116, 101])]
OUTPUT
[2, 0, 3, 1]
If you want to start indexing from 1, simply add one:
[sorted_list.index(e)+1 for i, e in enumerate([102, 97, 116, 101])]
OUTPUT
[3, 1, 4, 2]

Nir Alfasi
- 53,191
- 11
- 86
- 129
-
Is this sorting the list n times (n the number of elements in the sequence?) – Reblochon Masque Oct 24 '17 at 03:20
-
@ReblochonMasque good point, if you want more efficiency you can do it once outside the list comprehension and re-use the result – Nir Alfasi Oct 24 '17 at 03:22