使用 itertools 将列表拆分为递增的序列

Posted

技术标签:

【中文标题】使用 itertools 将列表拆分为递增的序列【英文标题】:Split a list into increasing sequences using itertools 【发布时间】:2017-02-14 22:06:44 【问题描述】:

我有一个包含混合序列的列表,例如

[1,2,3,4,5,2,3,4,1,2]

我想知道如何使用 itertools 将列表拆分为递增序列,在递减点处切割列表。例如上面会输出

[[1, 2, 3, 4, 5], [2, 3, 4], [1, 2]]

这是通过注意到序列在 2 处减少,所以我们在那里切割第一个位,另一个减少是在那里再次切割。

另一个例子是序列

[3,2,1]

输出应该是

[[3], [2], [1]]

如果给定的序列正在增加,我们将返回相同的序列。例如

[1,2,3]

返回相同的结果。即

[[1, 2, 3]]

对于像

这样的重复列表
[ 1, 2,2,2, 1, 2, 3, 3, 1,1,1, 2, 3, 4, 1, 2, 3, 4, 5, 6]

输出应该是

[[1, 2, 2, 2], [1, 2, 3, 3], [1, 1, 1, 2, 3, 4], [1, 2, 3, 4, 5, 6]]

我所做的是定义以下函数

def splitter (L):
    result = []
    tmp = 0
    initialPoint=0
    for i in range(len(L)):
       if (L[i] < tmp):
           tmpp = L[initialPoint:i]
           result.append(tmpp)
           initialPoint=i
       tmp = L[i]
    result.append(L[initialPoint:])
    return result

该功能 100% 工作,但我需要对 itertools 做同样的事情,这样我就可以提高代码的效率。有没有办法使用 itertools 包来避免显式循环?

【问题讨论】:

这是您认为可以改进的工作代码,请考虑Code Review。 是的。代码正在运行。我在想也许 itertools 包可以帮助改进它 【参考方案1】:

使用numpy,可以使用numpy.split,这需要索引作为分割位置;由于您想在值减小的地方拆分,您可以使用numpy.diff 计算差异并检查差异小于零的位置并使用numpy.where 检索相应的索引,问题中最后一种情况的示例:

import numpy as np
lst = [ 1, 2,2,2, 1, 2, 3, 3, 1,1,1, 2, 3, 4, 1, 2, 3, 4, 5, 6]
np.split(lst, np.where(np.diff(lst) < 0)[0] + 1)

# [array([1, 2, 2, 2]),
#  array([1, 2, 3, 3]),
#  array([1, 1, 1, 2, 3, 4]),
#  array([1, 2, 3, 4, 5, 6])]

【讨论】:

【参考方案2】:

Psidom 已经为您提供了一个很好的答案,但另一个 NumPy 解决方案是使用 scipy.signal.argrelmax 获取局部最大值,然后使用 np.split

from scipy.signal import argrelmax
arr = np.random.randint(1000, size=10**6)
splits = np.split(arr, argrelmax(arr)[0]+1)

【讨论】:

【参考方案3】:

假设您的原始输入数组:

a = [1, 2, 3, 4, 5, 2, 3, 4, 1, 2]

首先找到应该发生分裂的地方:

p = [ i+1 for i, (x, y) in enumerate(zip(a, a[1:])) if x > y ]

然后为每个这样的拆分创建切片:

print [ a[m:n] for m, n in zip([ 0 ] + p, p + [ None ]) ]

这将打印:

[[1, 2, 3, 4, 5], [2, 3, 4], [1, 2]]

我建议使用比pnm 等更多的口语名称;-)

【讨论】:

以上是关于使用 itertools 将列表拆分为递增的序列的主要内容,如果未能解决你的问题,请参考以下文章

为啥 itertools.chain 比扁平化列表理解更快?

[PY3]——过滤数据——列表推导filter()itertools.compress()

数组674. 最长连续递增序列

将元素列表拆分为组

动态规划-最长递增子序列

674. 最长连续递增序列