简体   繁体   English

从数字列表中生成所有可能组合的百分比

[英]Generate a percent of all possible combinations from a list of numbers

I know that itertools.combinations(iterable, r) returns combinations of a list/tuple of elements (as an iterable).我知道itertools.combinations(iterable, r)返回元素列表/元组的组合(作为可迭代对象)。 How can I build a function around it that returns only x% of all combinations?如何围绕它构建一个仅返回所有组合的 x% 的函数? (i just need a list of tuples, so it does not have to be an iterator). (我只需要一个元组列表,所以它不必是迭代器)。 I want that if there are very few combinations, for example nCn, it should return all (in this case one) of them (so minimum 1).我希望如果有很少的组合,例如 nCn,它应该返回所有(在这种情况下是一个)(因此最少为 1)。

With itertools.islice you can produce an iterator with an upper bound in the number of elements:使用itertools.islice您可以生成具有元素数量上限的迭代器:

import itertools

MAX_COMBS = 2
combs = itertools.combinations(range(3), 2)
combs_slice = itertools.islice(combs, MAX_COMBS)
print(*combs_slice, sep='\n')
# (0, 1)
# (0, 2)

If the size of the iterable has a len , then you can make the upper limit dependant on the total number of combinations:如果迭代的大小有一个len ,那么你可以根据组合的总数来设置上限:

import itertools
import math

# Percentage of combinations to draw
COMB_RATIO = 0.2
# Lower bound for number of combinations
MIN_COMBS = 2

iterable = range(5)
k = 3
combs = itertools.combinations(iterable, k)
max_combs = max(round(COMB_RATIO * math.comb(len(iterable), k)), MIN_COMBS)
combs_slice = itertools.islice(combs, max_combs)
print(*combs_slice, sep='\n')
# (0, 1, 2)
# (0, 1, 3)
# (0, 1, 4)

iterable = range(3)
k = 2
combs = itertools.combinations(iterable, k)
max_combs = max(round(COMB_RATIO * math.comb(len(iterable), k)), MIN_COMBS)
combs_slice = itertools.islice(combs, max_combs)
print(*combs_slice, sep='\n')
# (0, 1)
# (0, 2)

Note: math.comb was introduced in Python 3.8, if you are in a previous version you may need to roll your own implementation, or take it eg from SciPy .注意: math.comb是在 Python 3.8 中引入的,如果您在以前的版本中,您可能需要推出自己的实现,或者从 SciPy 等获取它。

Because iterators don't carry the information of how long their collections are, you cannot obtain the length from it.因为迭代器不携带它们的集合有多长的信息,所以你不能从中获取长度。

In your case, you could determine the size of the combination using the formula n!/(k! (nk)!) and iterate until your percentage.在您的情况下,您可以使用公式 n!/(k! (nk)!) 确定组合的大小并迭代直到您的百分比。

For instance:例如:

from math import factorial, ceil

def my_combinations():
    ratio = .2 # 20 percent
    a = range(10)
    n = len(a)
    k = 5
    it = itertools.combinations(a, k)
    total_combinations = factorial(n) / factorial(k) / factorial(n-k)

    for _ in range(ceil(total_combinations * ratio)):
        yield it.next()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM