假设n=6(列表长度) lis = 3, 2, 3, 4, 3, 1
我需要在最后一个元素之前有最大增长长度的子列表列表。它是:[3], [2, 3], [4, 3, 1]
如果lis = 3,2,3,4,3为5个元素,则结果应为[3,2,3],因为前面没有三个元素
发布于 2022-06-25 08:56:24
您可以使用:
def cut(l):
i = 1
pos = 0
out = []
while pos<len(l)-i+1:
out.append(l[pos:pos+i])
pos += i
i += 1
return out
cut([1,2,3,4,5,6,7,8,9,10,11])产出:
[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]变体
其他方法的乐趣,如果我们不想测试的位置相对于结束在每一步。
第一个n个整数的和是x = n*(n+1)/2,我们可以计算,给定x,n = int((math.sqrt(1+8*x)-1)/2)。这使我们能够直接知道有多少步骤:
# function to calculate the number of steps from the list length
def nb(x):
import math
return int((math.sqrt(1+8*x)-1)/2)
# nb(11) -> 4
def cut(l):
pos = 0
out = []
for i in range(1, nb(len(l))+1):
out.append(l[pos:pos+i])
pos += i
return out
cut([1,2,3,4,5,6,7,8,9,10,11])发布于 2022-06-25 08:54:44
最舒适的解决方案:
np.split(lis, np.cumsum(range(len(lis))))或者,用一些数学在这里:
np.split(lis, np.cumsum(range(int(np.ceil(np.sqrt(9/4 + 2*len(lst)) - 3/2)))))解决方案,没有numpy:
[lst[sum(range(i+1)):sum(range(i+1)) + i + 1] for i in range(len(lst)) if len(lst[sum(range(i+1)):])>=i]输出:[[3], [2, 3], [4, 3, 1]]
稍微短一点
[lst[l:l + i + 1] for i in range(len(lst)) if len(lst[(l := sum(range(i+1))):])>=i]正如@mozway所提到的,由于对累积和的反复评估,这种方法速度较慢。人们可以改变这种做法:
l = 0
[lst[l:(l := l + i + 1)] for i in range(len(lst)) if len(lst[l:])>=i]这是有点麻烦,但很有趣,尽管如此。
现在,利用这里的一些基本数学,我们可以得到相当快的
[lst[i*(i+1)//2 : (i+1)*(i+2)//2] for i in range(int(np.ceil(np.sqrt(9/4 + 2*len(lst)) - 3/2)))]起初,这是我的回答:
[lst[i:2*i + 1] for i in range(len(lst)) if len(lst[i:])>=i]但这从以前使用过的项目开始。
输出:[[3], [2, 3], [3, 4, 3], [4, 3, 1]]
发布于 2022-06-25 13:21:40
只是用一些itertools抛出另一个选项..。因此,它将适用于任何可以迭代的东西,而不仅仅是支持切片的对象。
from itertools import count, islice
# Make a generator so take the first N elements of what's remaining each time until we get an empty list...
chunk_iter = iter(lambda it=iter(lis), size=count(1): list(islice(it, next(size))), [])
# Filter out those to drop entries not matching the expected length (eg: drop last element if needed)
valid_chunks = (el for n, el in enumerate(chunk_iter, 1) if len(el) == n)
# Iterate over the above or optionally materialise into a list of lists...
# (and ignoring the very last entry if it's not the length of the number we're expecting)
res = list(valid_chunks)不过,将其封装到一个更易读的生成器函数中可能要好得多,例如:
def f(iterable):
it = iter(iterable)
for size in count(1):
val = list(islice(it, size))
if len(val) != size:
break
yield valhttps://stackoverflow.com/questions/72752308
复制相似问题