0

I have a list like

mylist=['foo/2.py','foo/12.py','foo/10.py','foo/1.py','foo/25.py']

and i need to get the index of the sort like

[3,2,1,0,4]

The answers of How to get indices of a sorted array in Python question's are not working as it get the index of a non natural sort

def natural_keys(text):
    return [ atoi(c) for c in re.split(r'(\d+)', text) ]

mylist=['foo/2.py','foo/12.py','foo/10.py','foo/1.py','foo/25.py']
print(mylist)
mylist.sort(key=natural_keys)
print(mylist)
ind=[i[0] for i in sorted(enumerate(mylist), key=lambda x:x[1])]
print(ind)
mylist=[mylist[i] for i in ind]
print(mylist)

gives

['foo/2.py', 'foo/12.py', 'foo/10.py', 'foo/1.py', 'foo/25.py']
['foo/1.py', 'foo/2.py', 'foo/10.py', 'foo/12.py', 'foo/25.py']
[0, 2, 3, 1, 4]
['foo/1.py', 'foo/10.py', 'foo/12.py', 'foo/2.py', 'foo/25.py']
martineau
  • 119,623
  • 25
  • 170
  • 301
NanBlanc
  • 127
  • 1
  • 12

4 Answers4

1

You can use the natsort package to achieve the natural sorting part.

from natsort import index_natsorted

mylist = ['foo/2.py','foo/12.py','foo/10.py','foo/1.py','foo/25.py']
ind = index_natsorted(mylist)

Results in [3, 0, 2, 1, 4] vs [3, 2, 1, 0, 4] with the default sort.

Martin Valgur
  • 5,793
  • 1
  • 33
  • 45
  • 1
    Actually, using [`index_natsorted`](https://natsort.readthedocs.io/en/master/api.html#index-natsorted) gives this directly. I was going to answer with this information, but I'll let you update this answer with that. – SethMMorton Aug 22 '19 at 17:10
  • As a bonus, to use the index to sort other lists you can use [`order_by_index`](https://natsort.readthedocs.io/en/master/api.html#order-by-index). – SethMMorton Aug 22 '19 at 17:15
0

This is one approach.

Ex:

mylist=['foo/2.py','foo/12.py','foo/10.py','foo/1.py','foo/25.py']
#print([mylist.index(i) for i in sorted(mylist)])
print([mylist.index(i) for i in sorted(mylist, key=lambda x: re.search(r"(\d+)\.py", x).group(1))])

Output:

[3, 2, 1, 0, 4]
Rakesh
  • 81,458
  • 17
  • 76
  • 113
0

This is another approach:

mylist=['foo/2.py','foo/12.py','foo/10.py','foo/1.py','foo/25.py']

print([i[0] for i in sorted(enumerate(mylist), key=lambda k: k[1])])

Prints:

[3, 2, 1, 0, 4]

EDIT: If you want to sort by number inside the string, you can do:

mylist=['foo/2.py','foo/12.py','foo/10.py','foo/1.py','foo/25.py']
import re
print([i[0] for i in sorted(enumerate(int(re.findall(r'\d+', v)[0]) for v in mylist), key=lambda k: k[1])])

Prints:

[3, 0, 2, 1, 4]
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
0

It would be easier if you create a mapping between the list elements and their position first

>>> mapping = {k:i for i,k in enumerate(mylist)}
>>> [mapping[k] for k in sorted(mylist)]
[3, 2, 1, 0, 4]

To get the indexes when sorted in natural order, you can feed in a custom key to sorted

>>> import re
>>> [mapping[k] for k in sorted(mylist, key=lambda word: tuple(map(int, re.findall(r'\d+', word))))]
[3, 0, 2, 1, 4]
Prem Anand
  • 2,469
  • 16
  • 16