首页 > 解决方案 > 检测数字列表中的峰值并记录它们的位置

问题描述

我正在尝试创建一些代码来返回数值数组的“峰值”(或局部最大值)的位置和值。

例如,列表在值为(since equals )arr = [0, 1, 2, 5, 1, 0]的位置有一个峰值。35arr[3]5

数组的第一个和最后一个元素不会被视为峰值(在数学函数的上下文中,您不知道之后和之前是什么,因此您不知道它是否是峰值)。

def pick_peaks(arr):
    print(arr)
    posPeaks = {
        "pos": [],
        "peaks": [],
    }
    startFound = False
    n = 0
    while startFound == False:
        if arr[n] == arr[n+1]:
            n += 1
        else:
            startFound = True

    endFound = False
    m = len(arr) - 1
    while endFound == False:
        if arr[m] == arr[m-1]:
            m -= 1
        else:
            endFound = True

    for i in range(n+1, m):
        if arr[i] == arr[i-1]:
            None
        elif arr[i] >= arr[i-1] and arr[i] >= arr[i+1]:
            posPeaks["pos"].append(i)
            posPeaks["peaks"].append(arr[i])

    return posPeaks

我的问题是高原。[1, 2, 2, 2, 1]有高峰而[1, 2, 2, 2, 3]没有。当高原是峰时,记录高原的第一个位置。

任何帮助表示赞赏。

标签: pythonlistdictionarycomparison-operators

解决方案


我建议您使用groupby对连续的相等值进行分组,然后为每个组存储第一个位置,例如[1, 2, 2, 2, 1]它在 tuples 列表之后创建以下列表[(1, 0), (2, 1), (1, 4)],将所有内容放在一起:

from itertools import groupby


def peaks(data):
    start = 0
    sequence = []
    for key, group in groupby(data):
        sequence.append((key, start))
        start += sum(1 for _ in group)

    for (b, bi), (m, mi), (a, ai) in zip(sequence, sequence[1:], sequence[2:]):
        if b < m and a < m:
            yield m, mi


print(list(peaks([0, 1, 2, 5, 1, 0])))
print(list(peaks([1, 2, 2, 2, 1])))
print(list(peaks([1, 2, 2, 2, 3])))

输出

[(5, 3)]
[(2, 1)]
[]

推荐阅读