Вычислить разницу между смежными элементами в списке python

У меня есть список миллионов чисел. Я хочу узнать, является ли разница между каждым числом в упорядоченном списке одинаковым для всего списка.

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

Ответ 1

Прямой подход здесь лучший:

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

Ответ 2

Использование чистого 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), которые могут сожрать вашу доступную память, если у вас есть миллионы чисел.

Ответ 3

Необходимо заметить, что в списке могут быть миллионы чисел. Поэтому в идеале мы не должны перебирать весь список, если это необходимо. Также нам нужно избегать создания нового списка, который может иметь значительное потребление памяти. Использование всех и генератора решает проблему

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

Ответ 4

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]

Ответ 5

Я пришел к этому во время игры:

>>> 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 answer, вы можете остановить выполнение раньше, когда какой-либо элемент будет найден не таким, как ваш первоначальный разброс:

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

Ответ 6

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

Ответ 7

Здесь приведен пример использования функции diff в numpy.

например.

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)

True

Ответ 8

Здесь решение, использующее итераторы только для сравнения.. и, возможно, преимущество не в необходимости знать длину ваших входных данных; вы могли бы избежать того, чтобы миллионы элементов списка загружались в память в первую очередь...

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