Encontrando diferencias entre elementos de una lista.

Dada una lista de números, ¿cómo encontrar diferencias entre cada ( i ) -th y ( i+1 ) -th de sus elementos? ¿Es mejor usar lambda o tal vez una lista de comprensión?

Ejemplo:
Dada una lista t=[1,3,6,...] , es encontrar una lista v=[2,3,...] porque 3-1=2 , 6-3=3 , etc.

 >>> t [1, 3, 6] >>> [ji for i, j in zip(t[:-1], t[1:])] # or use itertools.izip in py2k [2, 3] 

Las otras respuestas son correctas, pero si está haciendo un trabajo numérico, es posible que desee considerar numpy. Usando numpy, la respuesta es:

 v = numpy.diff(t) 

Si no quiere usar numpy ni zip , puede usar la siguiente solución:

 >>> t = [1, 3, 6] >>> v = [t[i+1]-t[i] for i in range(len(t)-1)] >>> v [2, 3] 

Puedes usar itertools.tee y zip para construir de manera eficiente el resultado:

 from itertools import tee # python2 only: #from itertools import izip as zip def differences(seq): iterable, copied = tee(seq) next(copied) for x, y in zip(iterable, copied): yield y - x 

O usar itertools.islice en itertools.islice lugar:

 from itertools import islice def differences(seq): nexts = islice(seq, 1, None) for x, y in zip(seq, nexts): yield y - x 

También puedes evitar el uso del módulo itertools :

 def differences(seq): iterable = iter(seq) prev = next(iterable) for element in iterable: yield element - prev prev = element 

Todas estas soluciones funcionan en espacio constante si no necesita almacenar todos los resultados y respaldar infinitos resultados.


Aquí hay algunos micro-puntos de referencia de las soluciones:

 In [12]: L = range(10**6) In [13]: from collections import deque In [15]: %timeit deque(differences_tee(L), maxlen=0) 10 loops, best of 3: 122 ms per loop In [16]: %timeit deque(differences_islice(L), maxlen=0) 10 loops, best of 3: 127 ms per loop In [17]: %timeit deque(differences_no_it(L), maxlen=0) 10 loops, best of 3: 89.9 ms per loop 

Y las otras soluciones propuestas:

 In [18]: %timeit [x[1] - x[0] for x in zip(L[1:], L)] 10 loops, best of 3: 163 ms per loop In [19]: %timeit [L[i+1]-L[i] for i in range(len(L)-1)] 1 loops, best of 3: 395 ms per loop In [20]: import numpy as np In [21]: %timeit np.diff(L) 1 loops, best of 3: 479 ms per loop In [35]: %%timeit ...: res = [] ...: for i in range(len(L) - 1): ...: res.append(L[i+1] - L[i]) ...: 1 loops, best of 3: 234 ms per loop 

Tenga en cuenta que:

  • zip(L[1:], L) es equivalente a zip(L[1:], L[:-1]) ya que zip ya termina en la entrada más corta, sin embargo evita una copia completa de L
  • El acceso a los elementos individuales por índice es muy lento porque cada acceso a índice es una llamada de método en Python
  • numpy.diff es lento porque primero tiene que convertir la list a un ndarray . Obviamente si comienzas con un ndarray será mucho más rápido:

     In [22]: arr = np.array(L) In [23]: %timeit np.diff(arr) 100 loops, best of 3: 3.02 ms per loop 

De acuerdo. Creo que encontré la solución adecuada:

 v = [x[1]-x[0] for x in zip(t[1:],t[:-1])] 

Un enfoque funcional:

 >>> import operator >>> a = [1,3,5,7,11,13,17,21] >>> map(operator.sub, a[1:], a[:-1]) [2, 2, 2, 4, 2, 4, 4] 

Usando generador:

 >>> import operator, itertools >>> g1,g2 = itertools.tee((x*x for x in xrange(5)),2) >>> list(itertools.imap(operator.sub, itertools.islice(g1,1,None), g2)) [1, 3, 5, 7] 

Utilizando índices:

 >>> [a[i+1]-a[i] for i in xrange(len(a)-1)] [2, 2, 2, 4, 2, 4, 4] 

Mi manera

 >>>v = [1,2,3,4,5] >>>[v[i] - v[i-1] for i, value in enumerate(v[1:], 1)] [1, 1, 1, 1]