我有一个列表需要拆分成多个不同大小的列表。原始列表中的值随大小逐渐增加,直到分割点,其中值在继续增加之前下降。拆分后,这些值必须保持有序。
E.g。 原始列表
[100, 564, 572, 578, 584, 590, 596, 602, 608, 614, 620, 625, 631, 70, 119,
125, 130, 134, 139, 144, 149, 154, 159, 614, 669, 100, 136, 144, 149, 153,
158, 163, 167, 173, 179, 62, 72, 78, 82, 87, 92, 97, 100, 107, 112, 117,
124, 426, 100, 129, 135, 140, 145, 151]
分手后:
[100, 564, 572, 578, 584, 590, 596, 602, 608, 614, 620, 625, 631]
[70, 119, 125, 130, 134, 139, 144, 149, 154, 159, 614, 669]
[100, 136, 144, 149, 153, 158, 163, 167, 173, 179]
[62, 72, 78, 82, 87, 92, 97, 100, 107, 112, 117, 124, 426]
[100, 129, 135, 140, 145, 151]
我搜索了一个解决方案,发现numpy.where
和numpy.diff
可能是候选人,但我不确定如何实施。
感谢您的帮助!
答案 0 :(得分:6)
方法#1
使用NumPy的numpy.split
将数组列表作为输出 -
import numpy as np
arr = np.array(a) # a is input list
out = np.split(arr,np.flatnonzero(arr[1:] < arr[:-1])+1)
方法#2
使用循环理解直接拆分列表,从而避免numpy.split
以提高效率 -
idx = np.r_[0, np.flatnonzero(np.diff(a)<0)+1, len(a)]
out = [a[idx[i]:idx[i+1]] for i in range(len(idx)-1)]
给定样本的输出 -
In [52]: idx = np.r_[0, np.flatnonzero(np.diff(a)<0)+1, len(a)]
In [53]: [a[idx[i]:idx[i+1]] for i in range(len(idx)-1)]
Out[53]:
[[100, 564, 572, 578, 584, 590, 596, 602, 608, 614, 620, 625, 631],
[70, 119, 125, 130, 134, 139, 144, 149, 154, 159, 614, 669],
[100, 136, 144, 149, 153, 158, 163, 167, 173, 179],
[62, 72, 78, 82, 87, 92, 97, 100, 107, 112, 117, 124, 426],
[100, 129, 135, 140, 145, 151]]
我们在这里使用np.diff
,在这种情况下以列表形式提供,然后计算差异。因此,更好的替代方案是转换为数组,然后使用它的移位切片之间的比较,而不是实际计算微分值。因此,我们也可以像这样idx
-
arr = np.asarray(a)
idx = np.r_[0, np.flatnonzero(arr[1:] < arr[:-1])+1, len(arr)]
让我们来看看它是否有任何进步 -
In [84]: a = np.random.randint(0,100,(1000,100)).cumsum(1).ravel().tolist()
In [85]: %timeit np.r_[0, np.flatnonzero(np.diff(a)<0)+1, len(a)]
100 loops, best of 3: 3.24 ms per loop
In [86]: arr = np.asarray(a)
In [87]: %timeit np.asarray(a)
100 loops, best of 3: 3.05 ms per loop
In [88]: %timeit np.r_[0, np.flatnonzero(arr[1:] < arr[:-1])+1, len(arr)]
10000 loops, best of 3: 77 µs per loop
In [89]: 3.05+0.077
Out[89]: 3.127
因此,转换和比较方法与转换相比有一个微小的改进:np.asarray(a)
吃饭大部分运行时。
答案 1 :(得分:4)
我知道你标记了numpy
。但这是一个没有任何依赖性的实现:
lst = [100, 564, 572, 578, 584, 590, 596, 602, 608, 614, 620, 625, 631, 70, 119,
125, 130, 134, 139, 144, 149, 154, 159, 614, 669, 100, 136, 144, 149, 153,
158, 163, 167, 173, 179, 62, 72, 78, 82, 87, 92, 97, 100, 107, 112, 117,
124, 426, 100, 129, 135, 140, 145, 151]
def split(lst):
last_pos = 0
for i in range(1, len(lst)):
if lst[i] < lst[i-1]:
yield lst[last_pos:i]
last_pos = i
if(last_pos <= len(lst)-1):
yield lst[last_pos:]
print([x for x in split(lst)])
答案 2 :(得分:-1)
如果您想使用numpy.diff
和numpy.where
,可以尝试
a = numpy.array(your original list)
numpy.split(a, numpy.where(numpy.diff(a) < 0)[0] + 1)
说明:
numpy.diff(a)
计算每个项目及其前一个项目的差异,并返回一个数组。
numpy.diff(a) < 0
返回一个布尔数组,其中每个元素都被它是否满足谓词所取代,在这种情况下小于零。这是numpy.ndarray
重载比较运算符的结果。
numpy.where
接受此布尔数组并返回元素不为零的索引。在此上下文中,False
的计算结果为零,因此您可以使用True
。
[0]
采用第一个(也是唯一的)轴
+ 1
你想在指数之后而不是在
最后,numpy.split
在给定的索引处将它们分开。