Много списка Python с некоторыми данными, как обнаружить данные в списке, встречаются вниз, а затем вверх. Например:
a1 = [8,6,4,1,-2,-6,5,8,9,87]
a2 = [8,6,4,1,-2,-6,5,-8,9,10]
где данные в a1 идут вниз, а затем вверх, ожидайте печати «ОК» но данные в a2 идут вниз, затем вверх, затем вниз, в последнюю очередь вверх, ожидайте печати 'NG' как это сделать на питоне?
Вы можете перебирать список по три элемента за раз и подсчитывать типы пиков, которые вы видите, либо вниз, либо вверх. В конце верните True
, если есть только одна нисходящая вершина, False
иначе.
def one_downward_peak(data):
upward_peaks = 0
downward_peaks = 0
for i in range(len(data) - 2):
a, b, c = data[i:i+3]
if a > b < c:
downward_peaks += 1
elif a < b > c:
upward_peaks += 1
return upward_peaks == 0 and downward_peaks == 1
>>> one_downward_peak([8,6,4,1,-2,-6,5,8,9,87])
True
>>> one_downward_peak([8,6,4,1,-2,-6,5,-8,9,10])
False
Если вы хотите оптимизировать это, вы можете выйти раньше, как только увидите восходящий пик.
Вы можете вычислить знак последовательных различий, а затем сохранить только разные. Если это дает [-1, 1]
, это OK
, иначе NG
:
import numpy as np
def check(lst):
# sign of successive difference
s = np.sign(np.diff(lst))
# mask to deduplicate successive values
m1 = np.r_[True, s[:-1]!=s[1:]]
# mask to remove flat lines
m2 = s != 0
# OK if both masks are True else NG
return 'OK' if s[m1&m2].tolist() == [-1, 1] else 'NG'
check(a1)
# 'OK'
check(a2)
# 'NG'
check([2,1,1,2])
# 'OK'
Промежуточные продукты:
### first example
lst
# [8, 6, 4, 1, -2, -6, 5, 8, 9, 87]
s = np.sign(np.diff(lst))
# array([-1, -1, -1, -1, -1, 1, 1, 1, 1])
s[np.r_[True, s[:-1]!=s[1:]]].tolist()
# [-1, 1]
### second example
lst
# [8, 6, 4, 1, -2, -6, 5, -8, 9, 10]
s = np.sign(np.diff(lst))
# array([-1, -1, -1, -1, -1, 1, -1, 1, 1])
s[np.r_[True, s[:-1]!=s[1:]]].tolist()
# [-1, 1, -1, 1]
Только что понял, что оба наших ответа не проходят проверку, когда пик плоский: .e.g. [2,1,1,2]
@flakes спасибо! Хорошо подмечено, с этим легко справиться, удалив 0
s, см. Обновление :)
Одним из простых способов исправить ваш код было бы использовать
itertools.groupby
для удаления плоских линий:data = [k for k,_ in itertools.groupby(data)]
в начале вашей функции.