1

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?

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 Answers3

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
  • 1
    If 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:

  1. Create a copy of the list and sort it (reversed). Call it sorted_list
  2. Create a third, empty list result
  3. Go through the input list and find the index of each number in the sorted_list list.
  4. 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
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