出于某些目的,我需要生成一个可迭代的对象,该对象列出一个列表的所有分区,但对子集长度有一个条件。
也就是说,如果列表的长度不是3的倍数,我想将列表划分为等长的子集(此处等于3),最后一个除外。
即['a','b','c','d','e']应该为所有分区分配2个长度为3和2的子集。
即,如果我只是使用:
[p for p in multiset_partitions(['a','b','c','d','e'],2)]
Out:
[[['a', 'b', 'c', 'd'], ['e']],
[['a', 'b', 'c', 'e'], ['d']],
[['a', 'b', 'c'], ['d', 'e']],
.....
[['a', 'd'], ['b', 'c', 'e']],
[['a', 'e'], ['b', 'c', 'd']],
[['a'], ['b', 'c', 'd', 'e']]]
我都知道了因此,到目前为止,我最好的尝试是过滤出至少包含一个长度> 3的子集的分区:
from sympy.utilities.iterables import multiset_partitions
def partitions(liste):
compte = 0
n = len(liste)//3 + 1
for p in multiset_partitions(liste,n):
l = len(p)
oversize = False
i = 0
while not(oversize) and i != l:
if len(p[i])>3:
oversize=True
i+=1
if oversize == False:
compte += 1
#do something with p
return(compte) #I'm just counting out the number of partitions right now
这可以解决问题,但显然不是实现我想要的最有效方法。
特别是当列表的长度增长时,分区的数量会迅速增加。
(长度为5时为10,但长度为10时为9100,而长度为13时为800800 ...)
什么是最有效的pythonic方法?
提前致谢,
蒂埃里
最佳答案
您始终可以将filter
包裹在分区函数周围。您可以使用lambda
函数来确保除最后一个元素外,所有元素的长度均为3。
list(filter(lambda x: all(len(z)==3 for z in x[:-1]), multiset_partitions('abcde', 2)))
# returns:
[[['a', 'b', 'c'], ['d', 'e']],
[['a', 'b', 'd'], ['c', 'e']],
[['a', 'b', 'e'], ['c', 'd']],
[['a', 'c', 'd'], ['b', 'e']],
[['a', 'c', 'e'], ['b', 'd']],
[['a', 'd', 'e'], ['b', 'c']]]
选择分区数时必须小心,以确保使用
ceil
。也就是说,对于10个项目,您要ceil(10/3)
而不是10//3
。关于python - 如何以子集长度为条件遍历列表的所有分区,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59303187/