index of items in a List in sorted order

Alex Martelli aleax at aleax.it
Mon Nov 25 04:03:16 EST 2002


Bengt Richter wrote:
   ...
>  >>> def ind_of_sorted2(L):
>  ...     items = zip(L,range(len(L)))
>  ...     items.sort()
>  ...     return zip(*items)
>  ...
>  >>> ind_of_sorted2(list('rgafrj'))
>  [('a', 'f', 'g', 'j', 'r', 'r'), (2, 3, 1, 5, 0, 4)]
> 
> Of course, it doesn't eliminate the duplicates, but now there's
> probably some time left to do that ;-)

If you want to keep the LAST index to any "duplicate" life's easy:

>>> def ind_of_sorted3(L):
...   items = dict(zip(L, range(len(L)))).items()
...   items.sort()
...   return zip(*items)
...
>>> ind_of_sorted3('rgafrj')
[('a', 'f', 'g', 'j', 'r'), (2, 3, 1, 5, 4)]
>>>

keeping the FIRST index instead ain't quite THAT smooth, e.g.:

>>> def ind_of_sorted4(L):
...   aux = zip(L, range(len(L)))
...   aux.reverse()
...   items = dict(aux).items()
...   items.sort()
...   return zip(*items)
...
>>> ind_of_sorted4('rgafrj')
[('a', 'f', 'g', 'j', 'r'), (2, 3, 1, 5, 0)]
>>>

dict, called with a sequence of pairs, is guaranteed to keep
the LAST pair out of any subset that has the same first item
(key), which is why reversing works here.  Of course, these
are all 2.2 solutions -- in 2.3 you can slice a list by [::-1] 
to get its reversed copy more smoothly:

>>> def ios5(L):
...   items = dict(zip(L,range(len(L)))[::-1]).items()
...   items.sort()
...   return zip(*items)
...
>>> ios5('rgafrj')
[('a', 'f', 'g', 'j', 'r'), (2, 3, 1, 5, 0)]
>>>

However, I think the several-statements approach of ind_of_sorted4
may be preferable -- more readable -- even if the alternate "squash
all into one statement" styles are available...


Alex




More information about the Python-list mailing list