En Python, ¿cómo indexo una lista con otra lista?


130

Me gustaría indexar una lista con otra lista como esta

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
T = L[ Idx ]

y T debería terminar siendo una lista que contiene ['a', 'd', 'h'].

¿Hay una mejor manera que

T = []
for i in Idx:
    T.append(L[i])

print T
# Gives result ['a', 'd', 'h']

Respuestas:


241
T = [L[i] for i in Idx]

77
¿Es esto más rápido que un bucle for o solo más corto?
Daniel Andrén

10
@daniel: ambos + recomendado
SilentGhost

14
Una prueba de sincronización rápida (sin pysco ni nada, así que haga lo que quiera) mostró la comprensión de la lista 2.5 veces más rápido que el ciclo (1000 elementos, repetidos 10000 veces).
James Hopkin

2
(usando un mapa y lambda es aún más lento - es de esperar, ya que llama a una función para cada iteración)
James Hopkin

+1 Si la lista de indexación es arbitraria, entonces la comprensión de la lista es el camino. Sin embargo, creo que, cuando sea posible, lo que parece no ser el caso aquí, los cortes son aún más rápidos.
Jaime

41

Si está usando numpy, puede realizar un corte extendido así:

>>> import numpy
>>> a=numpy.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
>>> Idx = [0, 3, 7]
>>> a[Idx]
array(['a', 'd', 'h'], 
      dtype='|S1')

... y probablemente sea mucho más rápido (si el rendimiento es una preocupación suficiente para molestarse con la importación numpy)


55
Mi prueba rápida de timeit mostró que usar np.array es en realidad casi 3 veces más lento (incluida la conversión a matriz).
Andrzej Pronobis

Funciona mejor si necesita convertirlo para operaciones de matriz de todos modos. Demasiado tiempo para las operaciones regulares de la lista.
frankliuao

9

Un enfoque funcional:

a = [1,"A", 34, -123, "Hello", 12]
b = [0, 2, 5]

from operator import itemgetter

print(list(itemgetter(*b)(a)))
[1, 34, 12]

Esto no funcionará si bcontiene solo un elemento.
blhsing


5

No estaba contento con ninguno de estos enfoques, por lo que se me ocurrió una Flexlistclase que permite una indexación flexible, ya sea por entero, por segmento o por índice:

class Flexlist(list):
    def __getitem__(self, keys):
        if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
        return [self[k] for k in keys]

Que, por ejemplo, usarías como:

L = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
Idx = [0, 3, 7]
T = L[ Idx ]

print(T)  # ['a', 'd', 'h']

que también demuestra el poder y la flexibilidad de Python!
crowie

Es muy fácil extender esto también para el código existente. Simplemente llame existing_list = Flexlist(existing_list)y tenemos la funcionalidad requerida sin descifrar ningún código
Yesh

1
L= {'a':'a','d':'d', 'h':'h'}
index= ['a','d','h'] 
for keys in index:
    print(L[keys])

Yo usaría un Dict adddeseado keysparaindex


0

También puede usar el __getitem__método combinado con maplo siguiente:

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
res = list(map(L.__getitem__, Idx))
print(res)
# ['a', 'd', 'h']
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.