4

Say I have a working list: ['a','b','c'] and an index list [2,1,0] which will change the working list to: ['c','b','a']

Is there any python method to do this easily (the working list may also be a numpy array, and so a more adaptable method is greatly preferred)? Thanks!

Johan Lundberg
  • 26,184
  • 12
  • 71
  • 97
Hailiang Zhang
  • 17,604
  • 23
  • 71
  • 117
  • 4
    This is trivial to write yourself. What have you tried? – Marcin Jan 25 '12 at 18:38
  • 1
    @Marcin Why was this closed as not a real question? I think it's a good question. Many things that are trivial to write already exist. In matlab for example there's a built in syntax for this. – Johan Lundberg Jan 25 '12 at 18:41
  • I know. The problem is that I have thousands of lists with the same length, and I want to re-order these thousands of list based on exactly the same new indices list. I am looking for a python function to do it easily, since there is a word called "pythonic", right? – Hailiang Zhang Jan 25 '12 at 18:42
  • 1
    @JohanLundberg: Because this is trivial in python. The OP seems to just be asking for someone else to write his code for him. – Marcin Jan 25 '12 at 18:43
  • IMO, Just because the answer is 'no' should not mean it's "not a question" – Johan Lundberg Jan 25 '12 at 18:43
  • Tip: use a generator expression and list indices. – Marcin Jan 25 '12 at 18:44
  • I don't know of a built-in method but here's a way: l=['a','b','c'] i=[2,1,0] def mapfunc(idx): return l[i] map(mapfunc,i) – Sid Jan 25 '12 at 18:46
  • 1
    I want to say seriously, this is not a homework for a lazy student. Yes, I can write my own method to deep copy all the thousands of lists, repeatedly re-order all of them based on the exactly same indices, and put them back to the original list. I really believe there might be a 'pythonic' way to solve it. As I am aware, the generator expression doesn't work for my case. – Hailiang Zhang Jan 25 '12 at 18:51
  • Your question is missing a pretty critical few words: "Is there any python method to it easily" -- what is that supposed to mean? – talonmies Jan 25 '12 at 18:53
  • 1
    http://docs.python.org/tutorial/datastructures.html hint, look for list comprehensions http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html hint, look for advanced indexing – Bi Rico Jan 25 '12 at 18:55
  • 1
    As you mentioned numpy, here is an answer for that case: you can do this directly, but it only works for numbers. Please read 'List-of-locations indexing'. http://www.scipy.org/Cookbook/Indexing#head-a8f6b64c733ea004fd95b47191c1ca54e9a579b5 the syntax is then myarray[myindexlist] – Johan Lundberg Jan 25 '12 at 18:55
  • @casperOne and Marci: It's cleary a question people try to answer so why not open it up and see where we can go? – Johan Lundberg Jan 25 '12 at 18:58
  • HailiangZhang - Why wouldn't a generator, or even a simple loop work for you? You haven't told us what you've tried, and why it doesn't work. – Marcin Jan 25 '12 at 19:03
  • Thanks Johan Lundberg! The numpy way of 'myarray[myindexlist]' is exactly what I am looking for, but sadly, it only works for numpy array, and hope there might be a more generic solution for regular list types as well. – Hailiang Zhang Jan 25 '12 at 19:04
  • An alternative buy ugly way is to convert all my lists (int, float, string...) to numpy array, map them based based on the indices list, and convert it back to the original list type. It is not elegant, but seems to be the most direct solution based on your kindly comments. – Hailiang Zhang Jan 25 '12 at 19:12
  • @HailiangZhang, I reposted my old comment as an answer. – Johan Lundberg Jan 25 '12 at 22:10

3 Answers3

5
  • ordinary sequence:

    L = [L[i] for i in ndx]
    
  • numpy.array:

    L = L[ndx]
    

Example:

>>> L = "abc"
>>> [L[i] for i in [2,1,0]]
['c', 'b', 'a']
jfs
  • 399,953
  • 195
  • 994
  • 1,670
3

Converting my comment-answer from when this question was closed:

As you mentioned numpy, here is an answer for that case:

For numerical data, you can do this directly with numpy arrays Details here: http://www.scipy.org/Cookbook/Indexing#head-a8f6b64c733ea004fd95b47191c1ca54e9a579b5

the syntax is then

myarray[myindexlist]

For non-numerical data, the most efficient way in the case of long arrays which you read out only once is most likely this:

(myarray[i] for i in myindex) 

note the () for generator expressions instead of [] for list comprehension.

Read this: Generator Expressions vs. List Comprehension

Community
  • 1
  • 1
Johan Lundberg
  • 26,184
  • 12
  • 71
  • 97
2

This is very easy to do with numpy if you don't mind converting to numpy arrays:

>>> import numpy
>>> vals = numpy.array(['a','b','c'])
>>> idx = numpy.array([2,1,0])
>>> vals[idx]
array(['c', 'b', 'a'], 
      dtype='|S1')

To get back to a list, you can do:

>>> vals[idx].tolist()
['c', 'b', 'a']
jterrace
  • 64,866
  • 22
  • 157
  • 202