2012-06-07 18 views
11

Decir que tengo una lista de elementos:¿Cuál es la forma más eficiente de iterar a través de una lista en python?

x = [1, 2, 3, 4, 5] 

tengo que realizar algunas funciones para cada uno de estos elementos. En cierto caso, necesito devolver el índice de un artículo.

¿Cuál es la mejor y más eficiente manera?

for item in list: 
    .... 

o

for i in range(len(list)): 
    .... 
+3

busque el foro antes de publicar. Esto ha sido respondido un millón de veces – sulabh

+0

posible duplicado de [Iterar una lista con índices en python] (http: // stackoverflow.com/questions/126524/iterate-a-list-with-indexes-in-python) – jamylak

+0

@sulabh: No encuentro el duplicado exacto de esta pregunta. Por favor, vincula lo mismo. La pregunta que estoy haciendo aquí es una comparación entre dos formas diferentes de iterar una lista, y una sugerencia de cuál es mejor. – mankand007

Respuesta

10
for item in list: 

es obviamente la que tiene un menor número de llamadas a funciones.

Si desea obtener el índice de los elementos a medida que avanza utilizar enumerate como esto

for pos, item in enumerate(collection): 
8
def loop_1(data): 
    for i in range(len(data)): 
     print(data[i]) 


def looper_2(data): 
    for val in data: 
     print(val) 

Comprobación con dis nos da el siguiente código de bytes para loop_1:

12  0 SETUP_LOOP    40 (to 43) 
      3 LOAD_GLOBAL    0 (range) 
      6 LOAD_GLOBAL    1 (len) 
      9 LOAD_FAST    0 (data) 
     12 CALL_FUNCTION   1 
     15 CALL_FUNCTION   1 
     18 GET_ITER    
    >> 19 FOR_ITER    20 (to 42) 
     22 STORE_FAST    1 (i) 

13  25 LOAD_GLOBAL    2 (print) 
     28 LOAD_FAST    0 (data) 
     31 LOAD_FAST    1 (i) 
     34 BINARY_SUBSCR  
     35 CALL_FUNCTION   1 
     38 POP_TOP    
     39 JUMP_ABSOLUTE   19 
    >> 42 POP_BLOCK   
    >> 43 LOAD_CONST    0 (None) 
     46 RETURN_VALUE   

El código de bytes para loop_2 se ve así:

17  0 SETUP_LOOP    24 (to 27) 
      3 LOAD_FAST    0 (data) 
      6 GET_ITER    
    >> 7 FOR_ITER    16 (to 26) 
     10 STORE_FAST    1 (val) 

18  13 LOAD_GLOBAL    0 (print) 
     16 LOAD_FAST    1 (val) 
     19 CALL_FUNCTION   1 
     22 POP_TOP    
     23 JUMP_ABSOLUTE   7 
    >> 26 POP_BLOCK   
    >> 27 LOAD_CONST    0 (None) 
     30 RETURN_VALUE 

La segunda versión es obviamente mejor.

2

Obviamente for i in range(len(list)): será más lento - es equivalente a esto:

list2 = range(len(list)) 

for i in list2: 
    ... 

Si ese fuera más rápido, entonces esto sería aún más rápido, ¿verdad?

list2 = range(len(list)) 
list3 = range(len(list2)) 
list4 = range(len(list3)) 

for i in list4: 
    ... 
4

Otra posible solución sería utilizar numpy que sería muy eficiente, para grandes listas tal vez incluso más eficiente que una lista por comprensión o un bucle.

import numpy as np 

a = np.arange(5.0) # a --> array([0., 1., 2., 3., 4.]) 

# numpy operates on arrays element by element 
# 
b =3.*a    # b --> array([0., 3., 6., 9., 12.]) 

Esta es una operación bastante simple pero puede ser más complejo usando una matriz como simplemente un argumento en una fórmula. Para matrices grandes, esto puede ser mucho más rápido que una lista de comprensión y hace que el código sea más limpio y fácil de leer (no es necesario crear una función para mapear en una lista de comprensión). También puede utilizar la indexación y rebanar a adaptar lo que quiere hacer:

Si desea tener acceso a las posiciones de índice reales utilizar ndenumerate

# b is as above 
for i, x in np.ndenumerate(b): 
    print i, x 

La salida de este bucle es:

(0,) 0.0 
(1,) 3.0 
(2,) 6.0 
(3,) 9.0 
(4,) 12.0 

NOTA: el índice devuelto como una tupla por numpy para manejar dimensiones adicionales. Aquí solo tenemos una dimensión única, por lo que tendría que descomprimir la tupla para obtener el índice del elemento.

+1

¿Puede agregar algún detalle al respecto? –

Cuestiones relacionadas