我有一个包含混合序列的列表,如
[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包来避免显式循环?
答案 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]]
我建议使用比p
,n
,m
等更多的发言名称; - )