2012-11-05 42 views
1

什麼是pythonic計算兩個列表的所有產品組合的方法。因此,給出兩個長度爲n的列表,我希望返回包含產品的長度爲2^n的列表。2個列表的Python組合

list(itertools.product(on,off))但結果應該使用所有四個要素,不僅組合對像:

[(1.05, 5.53), (1.05, 3.12), (1.05, 3.75), (1.05, 4.75), (1.5, 5.53), (1.5, 3.12), (1.5, 3.75), (1.5, 4.75), (2.1, 5.53), (2.1, 3.12), (2.1, 3.75), (2.1, 4.75), (1.7, 5.53), (1.7, 3.12), (1.7, 3.75), (1.7, 4.75)] 

因此,更多的是這樣的:

off = [5.53,3.12,3.75,4.75] 
on = [1.05,1.5,2.1,1.7] 

# calculate combinations 
x = combinations(on,off) 

# Where... 
# x[0] = off[0] * off[1] * off[2] * off[3] i.e 
# x[0] = 5.53 * 3.12 * 3.75 * 4.75 
# 
# x[1] = off[0] * off[1] * off[2] * on[3] i.e 
# x[1] = 5.53 * 3.12 * 3.75 * 1.7 
# 
# x[2] = off[0] * off[1] * on[2] * on[3] i.e 
# x[2] = 5.53 * 3.12 * 2.1 * 1.7 
# 
# ... 
# 
# x[15] = on[0] * on[1] * on[2] * on[3] i.e 
# x[15] = 1.05 * 1.5 * 2.1 * 1.7 

輸出可以是類似itertools.product()方法[(5.53, 3.12, 3.75, 4.75),(5.53, 3.12, 3.75, 1.7), ...]我需要計算產品,但我在組合方法中很有趣。

注:當我說這樣做的pythonic方式我的意思是簡單的一兩行取蟒蛇結構的優勢,圖書館(itertools ECT)

+0

您需要的名單的笛卡爾積? – Woot4Moo

+0

@ Woot4Moo不,這就是'itertools.product()'所做的。 –

回答

2

您可以通過itertools.product([0, 1], 4)開始生成所有2**4可能性。此列舉的0一切都可能序列和1小號長度爲4的,然後就可以通過利用off[i]如果0-1序列的第i個元素是0翻譯每0-1序列值從offon,一個序列,否則爲on[i]。在代碼:

>>> import itertools 
>>> off = [5.53,3.12,3.75,4.75] 
>>> on = [1.05,1.5,2.1,1.7] 
>>> for choices in itertools.product([0, 1], repeat=len(off)): 
...  print [(on[i] if choice else off[i]) for i, choice in enumerate(choices)] 
... 
[5.53, 3.12, 3.75, 4.75] 
[5.53, 3.12, 3.75, 1.7] 
[5.53, 3.12, 2.1, 4.75] 
[5.53, 3.12, 2.1, 1.7] 
... <10 more entries omitted ...> 
[1.05, 1.5, 2.1, 4.75] 
[1.05, 1.5, 2.1, 1.7] 

要打印的產品,而不是名單:

>>> import operator 
>>> for choices in itertools.product([0, 1], repeat=len(off)): 
...  elts = [(on[i] if choice else off[i]) for i, choice in enumerate(choices)] 
...  print reduce(operator.mul, elts, 1) 
... 
307.32975 
109.9917 
172.10466 
61.595352 
... 

如果您有可用numpy的,並願意與numpy的陣列,而不是Python列表的工作,然後有一些不錯的工具像numpy.choose可用。例如:

>>> import numpy 
>>> numpy.choose([0, 1, 0, 1], [off, on]) 
array([ 5.53, 1.5 , 3.75, 1.7 ]) 
>>> numpy.product(numpy.choose([0, 1, 0, 1], [off, on])) 
52.880624999999995 

與早期解決方案相結合,得出:

>>> for c in itertools.product([0, 1], repeat=4): 
...  print numpy.product(numpy.choose(c, [off, on])) 
... 
307.32975 
109.9917 
172.10466 
61.595352 
147.7546875 
52.880625 
... 
5

你們非常接近,itertools.combinations()

+0

我不認爲我的問題已經足夠清楚了'list(itertools.combinations(off + on,4))'產生了多少種方法來定購8個項目的長度爲4的組.. ..即n!/(k! (nk)!)= 70種方式。我想要16個二進制組合,將其視爲8支球隊正在玩的體育投注,4場比賽的結果數量是16種不同的組合。希望這清理了我所要求的。 –

+0

@sudo_o - 這似乎還不清楚。如果有8支球隊參加比賽,球隊如何配合? '關[i]'在'[i]'上播放'?如果是這樣的話,爲什麼你期望在[0]'上取代'x [1] = off [0] * off [1] * off [2] *而不是'x [1] = off [0] *關閉[1] *關[2] *關於[3]'? – mgilson

+0

@mgilson是''關[i]'vs'[i]'這是一個錯字,感謝您指出,我已經做了編輯。 –

0

這是你想要的東西:

off = [5.53,3.12,3.75,4.75] 
on = [1.05,1.5,2.1,1.7] 
import itertools as it 
import operator 

indices = list(it.product([0,1],[0,1],[0,1],[0,1])) 
off_on = off,on 
a = [reduce(operator.mul,(off_on[z][i] for i,z in enumerate(x))) for x in indices] 
print a 


#Numpy solution 
import numpy as np 
indices = list(it.product([0,1],[0,1],[0,1],[0,1])) 
off_on = off,on 
b = np.array([off,on]) 
loff = range(len(off)) 
aa = [np.prod(b[list(x),loff]) for x in indices] 

print aa 
print aa == a 
+0

請參閱我對Lattyware的答案和Mark Dickinson答案的評論。我認爲我不夠清楚,但我不想計算'n!/(k!(n-k)!' –

+0

我想我現在明白了。看到我更新的解決方案... – mgilson

+0

'打印len(一)'給出70不是16如此。 –