如何将列表拆分为单调递增/递减列表?

Spa*_*yie 5 python numpy list python-3.x

我有 python 列表,其中包含几个单调递减的元素。然而,所有这些序列并不彼此相邻 A = [[100, 83, 82, 51, 45, 29, 100, 100, 88, 88, 76, 76, 76, 59, 10, 12, 36, 100, 100, 86, 81, 79, 65, 65, 9, 10, 8]

我想 从 中提取a1 = [100, 83, 82, 51, 45, 29], a2=[100, 100, 88, 88, 76, 76, 76, 59, 10], 。正如您一定已经注意到的那样,我丢弃了 这些,因为它们不遵循任何模式。每个子数组的第一个元素应该大于 80。因此,我放弃了以 10 作为初始元素的单调子数组到目前为止,我有这个 。a3=[100, 100, 86, 81, 79, 65, 65, 9]A12,36,10,8A

def chop_array(array):
    itr = 0
    prev_element = 1e6
    window = list()
    mainWindow = list ()
    for i, element in enumerate(array):
        if element <= prev_element:
            window.append(element)
            prev_element = element
        else:
            mainWindow.append(window)
            prev_element = element
            window = list()
            window.append(element)
    filter_array = [True if item[0] > 80  else False for  item in mainWindow]
    return list(itertools.compress(mainWindow,filter_array))
Run Code Online (Sandbox Code Playgroud)

有没有更有效的方法在 python 中做到这一点?

Mus*_*dın 4

可以通过查看与前一个子列表的差异为正的位置来检测每个子列表的起始条目。然后我们可以将数组分割到这些位置;但由于np.diff将数组大小缩小了 1,因此我们在输出中添加 1 以获取相对于原始数组的索引:

>>> sub_lists = np.split(A, np.where(np.diff(A) > 0)[0] + 1)
>>> sub_lists

[array([100,  83,  82,  51,  45,  29]),
 array([100, 100,  88,  88,  76,  76,  76,  59,  10]),
 array([12]),
 array([36]),
 array([100, 100,  86,  81,  79,  65,  65,   9]),
 array([10,  8])]
Run Code Online (Sandbox Code Playgroud)

需要对此数组列表进行两种过滤:第一种是丢弃任何包含 1 项的列表,第二种是丢弃第一个条目小于 80 的列表。因此,

>>> result = [sub for sub in sub_lists if sub.size > 1 and sub[0] > 80]
>>> result

[array([100,  83,  82,  51,  45,  29]),
 array([100, 100,  88,  88,  76,  76,  76,  59,  10]),
 array([100, 100,  86,  81,  79,  65,  65,   9])]
Run Code Online (Sandbox Code Playgroud)

我们可以将它们包装在一个函数中:

def split_decreasing(arr, thre=80):
    """
    Splits the given array `arr` into monotonically decreasing subarrays
    of size at least 2 and first entries being at least `thre`.
    """
    split_points = np.where(np.diff(arr) > 0)[0] + 1
    sub_lists = np.split(arr, split_points)
    result = [sub for sub in sub_lists if sub.size > 1 and sub[0] > thre]
    return result
Run Code Online (Sandbox Code Playgroud)

样本运行:

>>> split_decreasing([63, 44, 43, 37, 30, 30, 27, 95, 91, 70, 65, 62, 62, 56, 56])

[array([95, 91, 70, 65, 62, 62, 56, 56])]

>>> split_decreasing(np.arange(10))
[]

>>> split_decreasing([12, 11, 7, 9, 7], thre=80)
[]

>>> split_decreasing([12, 11, 7, 9, 7], thre=10)
[array([12, 11,  7])]

>>> split_decreasing([12, 11, 7, 9, 7], thre=5)
[array([12, 11,  7]), array([9, 7])]

>>> split_decreasing([100, 83, 82, 51, 45, 29, 100, 100, 88, 88, 76, 76, 76,
                      59, 10, 12, 36, 100, 100, 86, 81, 79, 65, 65, 9, 10, 8])

[array([100,  83,  82,  51,  45,  29]),
 array([100, 100,  88,  88,  76,  76,  76,  59,  10]),
 array([100, 100,  86,  81,  79,  65,  65,   9])]
Run Code Online (Sandbox Code Playgroud)