3

Say I have a list [10, 5, 7] and I want to reduce it to something that indicates the relative orders [3, 1, 2]. I don't know how to convert this in Python.

  • 1
    That's not really a reduction; "reduce" usually means you wind up with fewer values than you started with (most often 1 from a list of many, in fact). – Mark Reed Oct 31 '13 at 20:23
  • Check this one out: http://stackoverflow.com/questions/10777271/python-using-enumerate-inside-list-comprehension Look into dictionary and enumerate. – crownedzero Oct 31 '13 at 20:24
  • @PatrickKostjens Really disgusting brute force approach where I iterate from 1 to the max value in the list and then check off the orders as I encounter them, but it's super slow and probably not worth using – user2175923 Oct 31 '13 at 20:25

4 Answers4

6

Try this, assuming there are no duplicate elements in the list:

lst = [10, 5, 7]
std = sorted(lst)

[std.index(e)+1 for e in lst]
=> [3, 1, 2]
Óscar López
  • 232,561
  • 37
  • 312
  • 386
1
start = [10, 5, 7]

Sort it

step1 = sorted(start) #if you have duplicates, sorted(set(start)) to uniquify

Make a lookup table

lookup = {v:i for i,v in enumerate(step1,1)}

Make your new list.

[lookup[x] for x in start]
Out[9]: [3, 1, 2]

This is O(nlogn) instead of the O(n**2) solution using repeated index searches. Timings:

test = [randrange(0,10000) for _ in range(10000)]

def f():
    std = sorted(test)
    return [std.index(e)+1 for e in test]

def g():
    step1 = sorted(test)
    lookup = {v:i for i,v in enumerate(step1,1)}
    return [lookup[x] for x in test]

%timeit f()
1 loops, best of 3: 1.17 s per loop

%timeit g()
100 loops, best of 3: 6.58 ms per loop
roippi
  • 25,533
  • 4
  • 48
  • 73
0
a = [10,5,7]
b = sorted(a)
newList = []
for i in a:
  newList.append(b.index(i))

print newList

Note that the output is [2,0,1] because the list is zero based, you could modify the code to append b.index(i)+1 if you wanted.

Tom Swifty
  • 2,864
  • 2
  • 16
  • 25
0
In [29]: L=[10,5,7]

In [30]: %paste
inds = {}
for v,k in enumerate(sorted(L),1):
  if k not in inds:
    inds[k] = []
  inds[k].append(v)
answer = [inds[k].pop() for k in L]

## -- End pasted text --

In [31]: answer
Out[31]: [3, 1, 2]
inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241