限制Python中的组合/排列数量

4 投票
3 回答
6800 浏览
提问于 2025-04-18 06:54

我本来打算用itertools生成一些组合,但我发现随着元素数量的增加,所需的时间会呈指数级增长。请问有没有办法限制或指明要生成的排列最大数量,这样itertools在达到这个限制后就会停止?

我想说的是:

目前我有

#big_list is a list of lists
permutation_list = list(itertools.product(*big_list))

现在这个排列列表有超过600万种排列。如果我再加一个列表,这个数字肯定会达到十亿。

我真正需要的是相对较少的排列(比如说5000个)。有没有办法限制生成的排列列表的大小?

3 个回答

0

你可以试试这个方法来获取特定数量的排列结果。排列的结果数量是用n!来表示的,其中n代表列表中元素的数量。比如说,如果你只想得到2个结果,你可以尝试下面的方法:

使用一个临时变量,并给它设定一个限制。

    from itertools import permutations
    m=['a','b','c','d']
    per=permutations(m)
    temp=1
    for i in list(per):
        if temp<=2:    #2 is the limit set
           print (i)
           temp=temp+1
        else:
           break
1

itertools.islice 有很多好处,比如可以设置 startstep。下面的解决方案灵活性不高,只适合在 start 为 0 和 step 为 1 的情况下使用。另一方面,它们不需要任何额外的导入。


你可以在 itertools.product 周围创建一个小的封装

it = itertools.product(*big_list)
pg = (next(it) for _ in range(5000)) # generator expression

(next(it) for _ in range(5000)) 这个表达式会返回一个生成器,它最多只能产生 5000 个值。你可以通过使用 list 构造函数将其转换为 list

pl = list(pg)

或者通过用方括号包裹生成器表达式(而不是用圆括号)来实现

pl = [next(it) for _ in range(5000)] # list comprehension

另一种解决方案和第一种一样高效,具体如下

pg = (p for p, _ in zip(itertools.product(*big_list), range(5000))

这个方法在 Python 3+ 中有效,其中 zip 会返回一个迭代器,当最短的可迭代对象耗尽时就会停止。转换为 list 的方式和第一种解决方案一样。

10

你需要使用 itertools.islice,像这样

itertools.islice(itertools.product(*big_list), 5000)

它不会把整个列表都放到内存里,而是返回一个迭代器,这个迭代器会懒惰地消耗实际的可迭代对象。你可以像这样把它转换成列表

list(itertools.islice(itertools.product(*big_list), 5000))

撰写回答