I have the following Python list (can also be a tuple):

myList = ['foo', 'bar', 'baz', 'quux'] 

I can say

>>> myList[0:3] ['foo', 'bar', 'baz'] >>> myList[::2] ['foo', 'baz'] >>> myList[1::2] ['bar', 'quux'] 

How do I explicitly pick out items whose indices have no specific patterns? For example, I want to select [0,2,3]. Or from a very big list of 1000 items, I want to select [87, 342, 217, 998, 500]. Is there some Python syntax that does that? Something that looks like:

>>> myBigList[87, 342, 217, 998, 500] 
2

8 Answers

list( myBigList[i] for i in [87, 342, 217, 998, 500] ) 

I compared the answers with python 2.5.2:

  • 19.7 usec: [ myBigList[i] for i in [87, 342, 217, 998, 500] ]

  • 20.6 usec: map(myBigList.__getitem__, (87, 342, 217, 998, 500))

  • 22.7 usec: itemgetter(87, 342, 217, 998, 500)(myBigList)

  • 24.6 usec: list( myBigList[i] for i in [87, 342, 217, 998, 500] )

Note that in Python 3, the 1st was changed to be the same as the 4th.


Another option would be to start out with a numpy.array which allows indexing via a list or a numpy.array:

>>> import numpy >>> myBigList = numpy.array(range(1000)) >>> myBigList[(87, 342, 217, 998, 500)] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: invalid index >>> myBigList[[87, 342, 217, 998, 500]] array([ 87, 342, 217, 998, 500]) >>> myBigList[numpy.array([87, 342, 217, 998, 500])] array([ 87, 342, 217, 998, 500]) 

The tuple doesn't work the same way as those are slices.

6

What about this:

from operator import itemgetter itemgetter(0,2,3)(myList) ('foo', 'baz', 'quux') 
1

Maybe a list comprehension is in order:

L = ['a', 'b', 'c', 'd', 'e', 'f'] print [ L[index] for index in [1,3,5] ] 

Produces:

['b', 'd', 'f'] 

Is that what you are looking for?

It isn't built-in, but you can make a subclass of list that takes tuples as "indexes" if you'd like:

class MyList(list): def __getitem__(self, index): if isinstance(index, tuple): return [self[i] for i in index] return super(MyList, self).__getitem__(index) seq = MyList("foo bar baaz quux mumble".split()) print seq[0] print seq[2,4] print seq[1::2] 

printing

foo ['baaz', 'mumble'] ['bar', 'quux'] 
1
>>> map(myList.__getitem__, (2,2,1,3)) ('baz', 'baz', 'bar', 'quux') 

You can also create your own List class which supports tuples as arguments to __getitem__ if you want to be able to do myList[(2,2,1,3)].

6

I just want to point out, even syntax of itemgetter looks really neat, but it's kinda slow when perform on large list.

import timeit from operator import itemgetter start=timeit.default_timer() for i in range(1000000): itemgetter(0,2,3)(myList) print ("Itemgetter took ", (timeit.default_timer()-start)) 

Itemgetter took 1.065209062149279

start=timeit.default_timer() for i in range(1000000): myList[0],myList[2],myList[3] print ("Multiple slice took ", (timeit.default_timer()-start)) 

Multiple slice took 0.6225321444745759

1

Another possible solution:

sek=[] L=[1,2,3,4,5,6,7,8,9,0] for i in [2, 4, 7, 0, 3]: a=[L[i]] sek=sek+a print (sek) 

like often when you have a boolean numpy array like mask

[mylist[i] for i in np.arange(len(mask), dtype=int)[mask]]

A lambda that works for any sequence or np.array:

subseq = lambda myseq, mask : [myseq[i] for i in np.arange(len(mask), dtype=int)[mask]]

newseq = subseq(myseq, mask)

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy