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

时间:2017-02-14 22:06:45

标签: python numpy itertools

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

[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包来避免显式循环?

3 个答案:

答案 0 :(得分:5)

使用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])]

答案 1 :(得分: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)

答案 2 :(得分:1)

假设您的原始输入数组:

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等更多的发言名称; - )