Pregunta Seleccione explícitamente elementos de una lista Python o tupla


Tengo la siguiente lista de Python (también puede ser una tupla):

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

puedo decir

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

¿Cómo selecciono explícitamente los elementos cuyos índices no tienen patrones específicos? Por ejemplo, quiero seleccionar [0,2,3]. O de una lista muy grande de 1000 artículos, quiero seleccionar [87, 342, 217, 998, 500]. ¿Hay alguna sintaxis de Python que haga eso? Algo que se parece a:

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

76
2017-07-09 01:49


origen


Respuestas:


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

Comparé las respuestas con 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] )

Tenga en cuenta que en Python 3, el 1er cambio fue el mismo que el 4to.


Otra opción sería comenzar con una numpy.array que permite la indexación a través de una lista o un 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])

los tuple no funciona de la misma forma que esas son rebanadas.


97
2017-07-09 01:53



¿Qué tal esto?

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

31
2017-07-09 01:52



No está incorporado, pero puede crear una subclase de lista que tome las tuplas como "índices" si lo desea:

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]

impresión

foo
['baaz', 'mumble']
['bar', 'quux']

9
2017-07-09 01:57



>>> map(myList.__getitem__, (2,2,1,3))
('baz', 'baz', 'bar', 'quux')

Tu también puedes crear el tuyo List clase que admite tuplas como argumentos para __getitem__ si quieres ser capaz de hacer myList[(2,2,1,3)].


5
2017-07-09 02:02



Tal vez una lista de comprensión esté en orden:

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

Produce:

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

¿Es esto lo que estás buscando?


3
2017-07-09 02:00



Solo quiero señalar, incluso la sintaxis de itemgetter se ve realmente ordenada, pero es un poco lenta cuando se realiza en una lista grande.

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 tomó 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))

Rebanada múltiple tomó 0.6225321444745759


0
2017-11-01 14:50



Otra posible solución:

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)

0
2017-11-18 20:32



como a menudo cuando tienes una matriz boolean numpy como mask

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

Una lambda que funciona para cualquier secuencia o np.array:

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

newseq = subseq(myseq, mask)


0
2017-07-16 15:26