Python - 列表元素之间的差异

问题描述:

给出一个数字列表如何找到每个元素(i)和(i+1)之间的差异 - 它的元素?应该更好地使用lambda还是列表理解?Python - 列表元素之间的差异

例: 给出一个列表t=[1,3,6,...]是找一个列表v=[2,3,...]因为3-1=26-3=3

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

如果你需要绝对的差异,'[ABS(JI)为I,J拉链(T,T [1:])]' – Anil 2015-07-14 00:09:48

确定。我认为我找到了合适的解决方案:

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

雅良好,但我认为它应该是 v = [x [0] -x [1] for zip in(t [1:],t [: - 1])] 已排序的列表! – 2016-01-31 10:38:08

其他答案是正确的,但如果你正在做数值工作,你可能要考虑numpy。使用numpy的,答案是:

v = numpy.diff(t) 

如果你不想使用numpy也不zip,您可以使用简单(简单的在我看来)的解决方案:

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

您可以使用itertools.teezip高效地构建结果:

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 

或者使用itertools.islice代替:

from itertools import islice 

def differences(seq): 
    nexts = islice(seq, 1, len(seq)) 
    for x, y in zip(seq, nexts): 
     yield y - x 

您也可以尽量避免使用itertools模块:

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

所有在不断的空间解决方案,这些工作,如果你不需要存储所有结果。 第一个也是最后一个解决方案也适用于无限可迭代,而第二个解决方案需要有限序列作为输入。


下面是解决方案的一些微基准测试:

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 

而另外提出的解决方案:

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 

需要注意的是:

  • zip(L[1:], L)相当于zip(L[1:], L[:-1])因为zip已经以最短的输入终止,但它避免了L的整个副本。
  • 通过索引访问单个元素是非常缓慢,因为每一个索引访问是在python方法调用
  • numpy.diff因为它首先将list转换为ndarray。显然,如果你ndarray开始这将是更快:

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

我的方式

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

使用'枚举'是浪费的,因为你没有使用'value'。请参阅https://*.com/a/16714453/832230 – 2016-11-25 08:01:16

的功能的方法:

>>> 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] 

使用发电机:

>>> 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] 

使用指数:

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