A veces necesito iterar una lista en Python mirando el elemento "actual" y el elemento "siguiente". Hasta ahora lo he hecho con un código como:
for current, next in zip(the_list, the_list[1:]):
# Do something
Esto funciona y hace lo que espero, pero ¿hay alguna forma más idiomática o eficiente de hacer lo mismo?
next
esta manera enmascara un elemento incorporado.next
también es una función incorporada en Python 2.Respuestas:
Aquí hay un ejemplo relevante de los documentos del módulo itertools :
Para Python 2, necesita en
itertools.izip
lugar dezip
:Cómo funciona esto:
Primero, se crean dos iteradores paralelos
a
yb
(latee()
llamada), ambos apuntando al primer elemento del iterable original. El segundo iterador,b
se mueve 1 paso adelante (lanext(b, None)
) llamada). En este puntoa
apunta a s0 yb
apunta a s1. Tantoa
yb
puede atravesar el iterador original de forma independiente - la función IZIP toma los dos iteradores y hace que los pares de elementos devueltos, avanzando dos iteradores al mismo ritmo.Una advertencia: la
tee()
función produce dos iteradores que pueden avanzar independientemente uno del otro, pero tiene un costo. Si uno de los iteradores avanza más que el otro, entoncestee()
necesita mantener los elementos consumidos en la memoria hasta que el segundo iterador los consuma también (no puede 'rebobinar' el iterador original). Aquí no importa porque un iterador está solo un paso por delante del otro, pero en general es fácil usar mucha memoria de esta manera.Y como
tee()
puede tomar unn
parámetro, esto también se puede usar para más de dos iteradores paralelos:fuente
zip(ł, ł[1:])
es mucho más corto y pitónicofuncy
módulo:funcy.pairwise
: funcy.readthedocs.io/en/stable/seqs.html#pairwise¡Ruede el suyo!
fuente
Como en
the_list[1:]
realidad crea una copia de toda la lista (excluyendo su primer elemento), yzip()
crea una lista de tuplas inmediatamente cuando se llama, en total se crean tres copias de su lista. Si su lista es muy grande, puede preferirque no copia la lista en absoluto.
fuente
the_list[1:]
solo crea un objeto de corte en lugar de una copia de casi toda la lista, por lo que la técnica del OP no es tan derrochadora como la haces sonar.[1:]
crea el objeto de división (o posiblemente "1:
"), que se pasa a__slice__
la lista, que luego devuelve una copia que contiene solo los elementos seleccionados. Una forma idiomática de copiar una lista esl_copy = l[:]
(que encuentro feo e ilegible, prefierol_copy = list(l)
)__slice__
un método especial.the_list[1:]
es equivalente athe_list[slice(1, None)]
, que a su vez es equivalente alist.__getitem__(the_list, slice(1, None))
.the_list[1:]
es solo una copia superficial, por lo que consta de un solo puntero por elemento de la lista. La parte más intensiva en memoria es lazip()
propia, porque creará una lista de unatuple
instancia por elemento de lista, cada una de las cuales contendrá dos punteros a los dos elementos y alguna información adicional. Esta lista consumirá nueve veces la cantidad de memoria que[1:]
consume la copia causada por .Solo estoy publicando esto, estoy muy sorprendido de que nadie haya pensado en enumerate ().
fuente
if
también se puede eliminar si usa rebanado:for (index, thing) in enumerate(the_list[:-1]): current, next_ = thing, the_list[index + 1]
Iterar por índice puede hacer lo mismo:
Salida:
fuente
i
siempre sea el índice del elemento actual.Esta es ahora una importación simple a partir del 16 de mayo de 2020
Documentos para más herramientas de iterto De manera este código es el mismo que en las otras respuestas, pero prefiero las importaciones cuando están disponibles.
Si aún no lo tiene instalado, entonces:
pip install more-itertools
Ejemplo
Por ejemplo, si tuviera la secuencia de fibbonnacci, podría calcular las proporciones de pares posteriores como:
fuente
Pares de una lista usando una comprensión de lista
Salida:
fuente
Estoy realmente sorprendido de que nadie haya mencionado la solución general más breve, simple y más importante :
Python 3:
Python 2:
Funciona para la iteración por pares pasando
n=2
, pero puede manejar cualquier número mayor:fuente
Una solución básica:
fuente
fuente