Python -列表元素之间的差异

时间:2020-12-25 18:27:11

Given a list of numbers how to find differences between every (i)-th and (i+1)-th of its elements? Should one better use lambda or maybe lists comprehension?

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

Example: Given a list t=[1,3,6,...] it is to find a list v=[2,3,...] because 3-1=2, 6-3=3, etc.

例:给定一个列表t=[1,3,6,…]是查找列表v=[2,3,……因为3-1=2,6-3=3,等等。

7 个解决方案

#1


104  

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

#2


71  

The other answers are correct but if you're doing numerical work, you might want to consider numpy. Using numpy, the answer is:

其他的答案是正确的,但是如果你做数值计算,你可能想考虑numpy。使用numpy,答案是:

v = numpy.diff(t)

#3


25  

If you don't want to use numpy nor zip, you can use the simple (simplest in my opinion) solution:

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

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

#4


8  

You can use itertools.tee and zip to efficiently build the result:

出现您可以使用itertools。tee和zip有效地构建结果:

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

Or using itertools.islice instead:

出现或使用itertools。islice相反:

from itertools import islice

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

You can also avoid using the itertools module:

您还可以避免使用itertools模块:

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

All these solution work in constant space if you don't need to store all the results and support infinite iterables.

如果不需要存储所有结果并支持无限的可迭代性,那么所有这些解决方案都可以在常量空间中工作。


Here are some micro-benchmarks of the solutions:

以下是解决方案的一些微观基准:

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

And the other proposed solutions:

及其他建议的解决方案:

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

Note that:

注意:

  • zip(L[1:], L) is equivalent to zip(L[1:], L[:-1]) since zip already terminates on the shortest input, however it avoids a whole copy of L.
  • zip(L[1:], L)等价于zip(L[1:], L[:-1]),因为zip已经终止于最短的输入,但是它避免了L的整个拷贝。
  • Accessing the single elements by index is very slow because every index access is a method call in python
  • 通过索引访问单个元素非常缓慢,因为在python中,每个索引访问都是一个方法调用
  • numpy.diff is slow because it has to first convert the list to a ndarray. Obviously if you start with an ndarray it will be much faster:

    numpy。diff很慢,因为它必须首先将列表转换为ndarray。显然,如果你从ndarray开始,它会快得多:

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

#5


3  

Ok. I think I found the proper solution:

好的。我认为我找到了合适的解决办法:

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

#6


3  

A functional approach:

功能的方法:

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

Using generator:

使用发电机:

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

Using indices:

使用指数:

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

#7


-1  

My way

我的方式

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

#1


104  

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

#2


71  

The other answers are correct but if you're doing numerical work, you might want to consider numpy. Using numpy, the answer is:

其他的答案是正确的,但是如果你做数值计算,你可能想考虑numpy。使用numpy,答案是:

v = numpy.diff(t)

#3


25  

If you don't want to use numpy nor zip, you can use the simple (simplest in my opinion) solution:

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

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

#4


8  

You can use itertools.tee and zip to efficiently build the result:

出现您可以使用itertools。tee和zip有效地构建结果:

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

Or using itertools.islice instead:

出现或使用itertools。islice相反:

from itertools import islice

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

You can also avoid using the itertools module:

您还可以避免使用itertools模块:

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

All these solution work in constant space if you don't need to store all the results and support infinite iterables.

如果不需要存储所有结果并支持无限的可迭代性,那么所有这些解决方案都可以在常量空间中工作。


Here are some micro-benchmarks of the solutions:

以下是解决方案的一些微观基准:

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

And the other proposed solutions:

及其他建议的解决方案:

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

Note that:

注意:

  • zip(L[1:], L) is equivalent to zip(L[1:], L[:-1]) since zip already terminates on the shortest input, however it avoids a whole copy of L.
  • zip(L[1:], L)等价于zip(L[1:], L[:-1]),因为zip已经终止于最短的输入,但是它避免了L的整个拷贝。
  • Accessing the single elements by index is very slow because every index access is a method call in python
  • 通过索引访问单个元素非常缓慢,因为在python中,每个索引访问都是一个方法调用
  • numpy.diff is slow because it has to first convert the list to a ndarray. Obviously if you start with an ndarray it will be much faster:

    numpy。diff很慢,因为它必须首先将列表转换为ndarray。显然,如果你从ndarray开始,它会快得多:

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

#5


3  

Ok. I think I found the proper solution:

好的。我认为我找到了合适的解决办法:

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

#6


3  

A functional approach:

功能的方法:

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

Using generator:

使用发电机:

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

Using indices:

使用指数:

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

#7


-1  

My way

我的方式

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