2010-10-03 14 views
10
a = [5, 66, 7, 8, 9, ...] 

¿Es posible hacer una iteración en lugar de escribir de esta manera?recorrido por pares de una lista o tupla

a[1] - a[0] 

a[2] - a[1] 

a[3] - a[2] 

a[4] - a[3] 

...

Gracias!

+4

¿en qué punto se queda atascado? ¿Qué código tienes hasta ahora? –

+0

posible duplicado de [Python - Diferencias entre los elementos de una lista] (http://stackoverflow.com/questions/2400840/python-differences-between-elements-of-a-list) – SilentGhost

Respuesta

7

Claro.

for i in range(1, len(a)): 
    print a[i] - a[i-1] 

No veo cuál es el verdadero problema aquí. ¿Has leído the python tutorial?

15

para una pequeña lista en Python 2 o cualquier lista en Python 3, puede utilizar

[x - y for x, y in zip(a[1:], a)] 

para una lista más grande, es probable que desee

import itertools as it 

[x - y for x, y in it.izip(a[1:], a)] 

si está utilizando Python 2

Y consideraría escribirlo como una expresión de generador en su lugar

(x - y for x, y in it.izip(a[1:], a)) 

Esto evitará crear la segunda lista en la memoria de una vez, pero solo podrá iterar una vez. Si solo quiere para iterar sobre él una vez, entonces esto es ideal y es bastante fácil cambiarlo si luego decide que necesita acceso aleatorio o repetido. En particular, si fuera a procesarlo para hacer una lista, esta última opción es ideal.

actualización:

El método más rápido, con mucho, es

import itertools as it 
import operator as op 

list(it.starmap(op.sub, it.izip(a[1:], a))) 

$ python -mtimeit -s's = [1, 2]*10000' '[x - y for x, y in zip(s[1:], s)]' 
100 loops, best of 3: 13.5 msec per loop 

$ python -mtimeit -s'import itertools as it; s = [1, 2]*10000' '[x - y for x, y in it.izip(s[1:], s)]' 
100 loops, best of 3: 8.4 msec per loop 

$ python -mtimeit -s'import itertools as it; import operator as op; s = [1, 2]*10000' 'list(it.starmap(op.sub, it.izip(s[1:], s)))' 
100 loops, best of 3: 6.38 msec per loop 
+8

en realidad se ven demasiado complicados para un trivial tarea, especialmente teniendo en cuenta la experiencia asumida OP. ¿Cuándo se convirtieron los bucles for-loop normales en algo malo? –

+5

cuando se convirtió en el doble de lento y más pesado de leer que una comprensión. – aaronasterling

+0

Ok, hice un perfil y en este caso no son dos veces más lentos, pero siguen siendo los más lentos por el momento. 16.8 mseg con la misma entrada que la mostrada arriba. y mi punto sobre ellos siendo más cruxtier para leer todavía está en pie. – aaronasterling

42

El uso de range está perfectamente bien. Sin embargo, la programación (como las matemáticas) se basa en las abstracciones. Los pares consecutivos [(x0, x1), (x1, x2), ..., (xn-2, xn-1)], se llaman combinaciones de pares, consulte por ejemplo un recipe in the itertools docs. Una vez que tenga esta función en su conjunto de herramientas, se puede escribir:

for x, y in pairwise(xs): 
    print(y - x) 

O, como una expresión del generador:

consecutive_diffs = (y - x for (x, y) in pairwise(xs)) 
0

Aquí está el ejemplo de los reciepes itertools:

from itertools import tee 

def pairwise(iterable): 
    "s -> (s0,s1), (s1,s2), (s2, s3), ..." 
    a, b = tee(iterable) 
    next(b, None) 
    return zip(a, b) 

Lo cual no es muy legible. Si prefiere algo más comprensible y entiende cómo funcionan los generadores, aquí un ejemplo más largo con el mismo resultado:

def pairwise(it): 
    """ 
    Walk a list in overlapping pairs. 

    >>> list(pairwise([0, 1, 2, 3, 4, 5])) 
    [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)] 
    """ 
    it = iter(it) 
    start = None 
    while True: 
     if not start: 
      start = next(it) 
     end = next(it) 
     yield start, end 
     start = end 
0
def pairwise(iterable): 
    i = iter(iterable) 
    while True: 
     yield next(i), next(i, '') 
+0

Debe agregar algunos comentarios al código. – timiTao

+0

Si bien este código puede responder a la pregunta, proporcionar un contexto adicional con respecto a por qué y/o cómo responde este código a la pregunta mejora su valor a largo plazo. –

Cuestiones relacionadas