Python-различия между элементами списка
учитывая список чисел, как найти различия между каждым (i
)-й и (i+1
)-го элементов? Следует ли лучше использовать лямбда или, может быть, списки понимания?
пример:
Учитывая список t=[1,3,6,...]
найти список v=[2,3,...]
, потому что 3-1=2
,6-3=3
и т. д.
7 ответов:
другие ответы верны, но если вы делаете численную работу, вы можете рассмотреть 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.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
или через
itertools.islice
вместо:from itertools import islice def differences(seq): nexts = islice(seq, 1, None) 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
. Очевидно, если вы start Сndarray
будет много быстрее:In [22]: arr = np.array(L) In [23]: %timeit np.diff(arr) 100 loops, best of 3: 3.02 ms per loop
функциональный подход:
>>> 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]