我在制作系数组合时遇到了麻烦。基本上我有一个项目列表,并希望得到所有独特的系数组合,如下所示:
dog:1 cat:1
dog:2 cat:1
dog:3 cat:1
dog:1 cat:2
dog:2 cat:2
我不确定这样做的最佳方式(动态编程,递归,暴力等等)所以我试着从递归开始:
list = ["dog", "cat"]
coeff = [1] * len(list)
main_queue = []
def recursion(k, list):
for item in list[0:k-1]:
for data in range(5):
coeff_temp = coeff
coeff_temp[k] = data
main_queue.append(coeff_temp)
#print item, data
if k == (len(list)-1):
return
else:
recursion(k+1, list)
recursion(0, list)
print "*" * 30
for x in main_queue:
print x
输出是:
******************************
[4, 1]
[4, 1]
[4, 1]
[4, 1]
[4, 1]
它只更改我所创建的主队列中的最后一个条目。我做错了什么?
P.S。这是最好的方法(范围在1-5之间,列表中将有大约20-30个项目......我最好使用动态编程)?
答案 0 :(得分:2)
data = ["dog", "cat"]
upto = 4
def all_combos(items, upto):
if items < 1:
yield []
else:
for r in range(upto+1):
for rest in all_combos(items-1, upto):
yield [r] + rest
for coeffs in all_combos(len(data), upto):
print ", ".join("{}s: {}".format(n, coeff) for n,coeff in zip(data,coeffs))
结果
dogs: 0, cats: 0
dogs: 0, cats: 1
dogs: 0, cats: 2
dogs: 0, cats: 3
dogs: 0, cats: 4
dogs: 1, cats: 0
dogs: 1, cats: 1
dogs: 1, cats: 2
dogs: 1, cats: 3
dogs: 1, cats: 4
dogs: 2, cats: 0
dogs: 2, cats: 1
dogs: 2, cats: 2
dogs: 2, cats: 3
dogs: 2, cats: 4
dogs: 3, cats: 0
dogs: 3, cats: 1
dogs: 3, cats: 2
dogs: 3, cats: 3
dogs: 3, cats: 4
dogs: 4, cats: 0
dogs: 4, cats: 1
dogs: 4, cats: 2
dogs: 4, cats: 3
dogs: 4, cats: 4
这就是你所追求的。 请记住组合的数量将为(len(data))**upto
,这会随着数据的增长而爆炸式增长。
编辑:正如已经指出的那样,实现这一目标的另一种方法是
from itertools import product
def all_combos(items, upto):
return product(*(range(upto+1) for i in range(items)))
答案 1 :(得分:1)
你的错误是这一行:
coeff_temp = coeff
这不会复制coeff
:它引用同一个对象。当你在下一行修改它时:
coeff_temp[k] = data
你正在修改你到目前为止插入的每一个 - 它们都是相同的列表!
要实际复制列表,请使用:
coeff_temp = list(coeff)
或
coeff_temp = coeff[:]
以下是您问题的最佳解决方案:
import itertools
data = {
"dog": xrange(1, 5),
"cat": xrange(1, 5)
#add more here...
}
combinations = (dict(zip(data.keys(), c)) for c in itertools.product(*data.values()))
for c in combinations:
print c
答案 2 :(得分:1)
在我看来,你想要的是一个N位数的基数为M的数字,其中N是列表中的项目数,M是每个项目的可能值数。
例如,如果列表中有3个项目,并且每个项目的值都是1到4,那么您将使用3位数的基数3。由于您的第一个数字是1
,因此当您将其分配给列表项时,您将为每个数字添加一个数字。
在此,第一列是您计算的实际数字,第二列是相同的数字,每个数字加1,然后分配给三个动物中的每一个的值:
000 111 cat 1 dog 1 hamster 1
001 112 cat 1 dog 1 hamster 2
002 113 cat 1 dog 1 hamster 3
010 121 cat 1 dog 2 hamster 1
011 122 cat 1 dog 2 hamster 2
012 123 cat 1 dog 2 hamster 3
020 131 cat 1 dog 3 hamster 1
021 132 cat 1 dog 3 hamster 2
022 133 cat 1 dog 3 hamster 3
100 211 cat 2 dog 1 hamster 1
以及其他3位数的3号基数。
答案 3 :(得分:0)
尝试查看itertools lib http://docs.python.org/library/itertools.html,在那里你可以找到combination()函数,它必须帮助你。
答案 4 :(得分:0)
如果你想要组合,那么递归几乎是所有时间都是正确的答案。
您的代码存在问题:在recursion
功能内,当您说coeff_temp = coeff
您正在将参考复制到coeff
时,您的所在每次都附加相同的列表。这就是为什么 。否则这个方法对我来说似乎很好。
更改行
coeff_temp = coeff
到
coeff_temp = list(coeff)
复制列表,并继续从那里开始。
itertools模块是一个很好的组合解决方案。