我有一个包含数百万个数字的列表。 我想知道有序列表中每个数字之间的差异对于整个列表是否相同。
list_example = [ 0, 5, 10, 15, 20, 25, 30, 35, 40, ..etc 等等]
最好的方法是什么?
我的尝试:
import collections
list_example = [ 0, 5, 10, 15, 20, 25, 30, 35, 40 ]
count = collections.Counter()
for x,y in zip(list_example[0::],list_example[1::]):
print x,y,y-x
count[y-x] +=1
if len( count ) == 1:
print 'Differences all the same'
结果:
0 5 5
5 10 5
10 15 5
15 20 5
20 25 5
25 30 5
30 35 5
35 40 5
Differences all the same
使用纯Python:
>>> x = [0,5,10,15,20]
>>> xdiff = [x[n]-x[n-1] for n in range(1,len(x))]
>>> xdiff
[5, 5, 5, 5]
>>> all([xdiff[0] == xdiff[n] for n in range(1,len(xdiff))])
True
如果您使用 NumPy,会更容易,而且可能更快:
>>> import numpy as np
>>> xdiff = np.diff(x)
>>> np.all(xdiff[0] == xdiff)
True
但是这两个都会创建两个额外的列表(或数组,在 NumPy 的情况下),如果您有数百万个数字,这可能会耗尽您的可用内存。
这里直接的方法是最好的:
x = s[1] - s[0]
for i in range(2, len(s)):
if s[i] - s[i-1] != x: break
else:
#do some work here...
需要注意的是,该列表可能有数百万个号码。因此,理想情况下,除非有必要,否则我们不应该迭代整个列表。此外,我们需要避免构造新列表,这可能会消耗大量内存。使用所有和生成器将解决问题
>>> x = [5, 10, 15, 20, 25]
>>> all(x[i] - x[i-1] == x[i+1] - x[i] for i in xrange(1, len(x) - 1))
True
itertools.izip 非常适合这种事情:
>>> lst = [1,1,2,3,5,8]
>>> [y-x for x, y in itertools.izip (lst, lst[1:])]
[0, 1, 1, 2, 3]
我在玩的时候发现了这个:
>>> exm = [0,5,10,15,20,25,30,35]
>>> len(set(exm[a + 1] - exm[a] for a in range(0, len(exm) - 1))) == 1
我所做的是对于每对连续的项目确定它们在生成器中的差异。 然后,我将所有这些差异添加到一个集合中,以仅保留唯一值。如果该集合的长度为 1,则所有差异都相同。
编辑:查看cldy的答案,当发现任何项目与您的初始差异不同时,您可以提前停止执行:
>>> exm = [0,5,10,15,20,25,30,35]
>>> initial_diff = exm[1] - exm[0]
>>> difference_found = any((exm[a + 1] - exm[a]) != initial_diff
for a in range(1, len(exm) - 1))
>>> x=[10,15,20,25]
>>> diff=(x[-1]-x[0])/(len(x)-1)
>>> diff
5
>>> all(x[i]+diff==x[i+1] for i in range(len(x)-1))
True
这是在 numpy
中使用
diff 函数的示例。
例如
import numpy
numpy_array = numpy.zeros(10**6)
for i in xrange(10**6):
numpy_array[i] = i
print numpy.any(numpy.diff(a) == 1)
正确
这是一个使用迭代器进行比较的解决方案......并且可能有一个优点,即不需要知道输入数据的长度;您也许能够避免首先将数百万个列表项加载到内存中...
from itertools import tee, izip
# From itertools recipes: http://docs.python.org/library/itertools.html
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
class DifferenceError(Exception):
pass
def difference_check(data):
idata = pairwise(data)
(a,b) = idata.next()
delta = b - a
for (a,b) in idata:
if b - a != delta:
raise DifferenceError("%s -> %s != %s" % (a,b,delta))
return True
我也遇到了类似的问题,我使用了以下方法:
foo = map(lambda x: lst[x+1]-lst[x],range(len(lst)-1))
截至 2024 年,这非常容易(
itertools
是 sweet):
>>> l = list(range(1, 100))
>>> import itertools
>>> [p[1] - p[0] for p in itertools.pairwise(l)]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>>>