给定一组项目,例如:
[ 1, 2, 3, 4, 5, 6 ]
我希望通过重复生成一定长度的所有可能组合。扭曲是我想以预定的组合开始(一种偏移到组合列表中)。
例如,从这开始:
[ 1, 5, 6 ]
第一个(下一个)组合将是:
[ 1, 6, 6 ]
我已经成功使用itertools.combinations_with_replacement()
来生成组合,但是这个项目需要使用一个生成太多组合的集合 - 首先创建它们并迭代到正确的点不是可能的。
我发现this example for generating kth combination似乎对我来说效果不佳。 This answer似乎是另一种可能性,但我似乎无法将它从C移植到Python。
到目前为止,这是使用kth combination example:
的代码import operator as op
items = [ 1,2,3,4,5,6 ]
# https://stackoverflow.com/a/4941932/1167783
def nCr(n, r):
r = min(r, n-r)
if r == 0:
return 1
numer = reduce(op.mul, xrange(n, n-r, -1))
denom = reduce(op.mul, xrange(1, r+1))
return numer // denom
# https://stackoverflow.com/a/1776884/1167783
def kthCombination(k, l, r):
if r == 0:
return []
elif len(l) == r:
return l
else:
i = nCr(len(l)-1, r-1)
if k < i:
return l[0:1] + kthCombination(k, l[1:], r-1)
else:
return kthCombination(k-i, l[1:], r)
# get 1st combination of 3 values from list 'items'
print kthCombination(1, items, 3)
# returns [ 1, 2, 4 ]
任何帮助都会很棒!
答案 0 :(得分:3)
如果假设数组中的所有值都是base-n编号系统中的数字,其中n是数组的长度,则第k个组合将等于以base-n表示的k。
如果您想要从给定组合开始(即[1,6,5])并从那里继续,只需将此起点读作base-n中的数字。然后,您可以通过递增来开始迭代连续组合。
编辑:进一步解释:
让我们从数组开始吧。该数组包含6个值,因此我们在base-6中工作。我们假设数组中每个元素的索引是元素的base-6值。
base-6中的值范围从0到5.这可能会让人感到困惑,因为我们的示例使用数字,但我们可以使用任何组合来完成此操作。我会在我们合并的数字周围加上“引号”标记。
给定组合['1','6','5'],我们首先需要将其转换为base-6值。 '1'变为0,'6'变为5,'5'变为4.使用它们在起始值中的位置作为它们在base-6中的幂,我们得到:
(0 * 6 ^ 0)+(5 * 6 ^ 1)+(4 * 6 ^ 2)= 174(十进制)
如果我们想知道下一个组合,我们可以添加1.如果我们想要提前知道20个组合,我们添加20.我们也可以减去倒退。让我们添加1到174并将其转换回base-6:
175(十进制)=(1 + 6 ^ 0)+(5 * 6 ^ 1)+(4 * 6 ^ 2)= 451(base-6)= ['2','6','5 '](组合)
有关数字基础的更多信息,请参阅http://en.wikipedia.org/wiki/Radix和http://en.wikipedia.org/wiki/Base_%28exponentiation%29
答案 1 :(得分:2)
您可以映射数字,而不是发明轮次时间数37,289,423,987,239,489,826,364,653(仅计算人类)。 itertools
将返回第一个组合[1,1,1]
,但您需要[1,5,6]
。只需将[0,4,5] mod 6添加到每个位置即可。当然,您也可以在数字,对象和模数之间来回映射。
即使每个位置的元素数量不同,这也有效。
不过,你会对你的开始有更多的乐趣。