У меня есть список:
l = [[8,7,6], [9,9,9], [4,5,9], [1,5,1]]
и я хотел бы найти максимальное значение вычитания элементов между двумя последовательными списками. Пример:
Между [9,9,9]
и [8,7,6]
→ макс [1,2,3]
→ 3
Между [4,5,9]
и [9,9,9]
→ макс [5,4,0]
→ 5
Между [1,5,1]
и [4,5,9]
→ макс [3,0,8]
→ 8
И тогда я хотел бы иметь список с [3,5,8]
Поскольку я код должен быть совместим с версией 1.6.1 numpy
, я делаю так:
new_l = []
for index, i in enumerate(l):
if index < len(l)-1:
t = []
for jndex, j in enumerate(i):
t.append(l[index +1][jndex] - l[index][jndex])
new_l.append(max([abs(number) for number in t]))
new_l = new_l[:-1]
Есть ли способ лучше? заранее спасибо
С помощью обычного Python вы можете использовать понимание списка с zip
дважды:
L = [[8,7,6], [9,9,9], [4,5,9], [1,5,1]]
res = [max(abs(i-j) for i, j in zip(*values)) for values in zip(L, L[1:])]
[3, 5, 8]
Следующее вложенное понимание будет работать:
l = [[8,7,6], [9,9,9], [4,5,9], [1,5,1]]
[max(map(abs, (x-y for x, y in zip(a, b)))) for a, b in zip(l, l[1:])]
# [3, 5, 8]
zip(l, l[1:])
создает пары соседних списков, которые затем снова zip(l, l[1:])
молнии, чтобы получить попарные различия.
Согласно комментарию @Divakar, это стандартное решение NumPy:
res = np.abs(np.diff(L, axis=0)).max(1)
Для больших массивов вы можете увидеть значительное улучшение производительности с помощью numba
. Обе версии более эффективны, чем не-векторизованное понимание списка Python.
from numba import njit
L = np.array([[8,7,6], [9,9,9], [4,5,9], [1,5,1]] * 10**6)
@njit
def differ(A):
res = np.zeros(A.shape[0]-1)
for i in range(A.shape[0]-1):
for j in range(A.shape[1]):
res[i] = max(res[i], abs(A[i+1, j] - A[i, j]))
return res
assert np.array_equal(np.abs(np.diff(L, axis=0)).max(1), differ(L))
%timeit np.abs(np.diff(L, axis=0)).max(1) # 161 ms per loop
%timeit differ(L) # 53.7 ms per loop
%timeit [max(abs(i-j) for i, j in zip(*v)) for v in zip(L, L[1:])] # 22.5 s per loop
np.abs(np.diff(l,axis=0)).max(1)
.