2013-10-07 15 views
1

我試過尋找這個問題的答案,並閱讀了很多關於裝飾器和全局變量,但還沒有發現任何與手頭問題完全相符的意義:我想讓N的每個排列長度使用A-alpha,fxn(A,N)。我將通過函數2參數:AN。它會產生長度爲N的虛擬結果。然後,與N嵌套for循環它將更新結果的每個索引,每個元素A從最內層循環開始。因此,與fxn(‘01’,4)會產生如何在Python中產生嵌套循環

1111, 1110, 1101, 1100, 1011, 1010, 1001, 1000, 
0111, 0110, 0101, 0100, 0011, 0010, 0001, 0000 

這是簡單的做到這一點,如果你知道你有多少嵌套循環需要(N;雖然超過4它開始帶來麻煩和繁瑣)。但是,如果要使用A來創建所有任意長度的序列,則需要一些方法來自動執行此循環行爲。特別是我還希望這個函數作爲一個生成器來防止必須將所有這些值存儲在內存中,比如列表。要啓動它,需要初始化第一個循環並通過單個值更改(要更新的索引)來保持初始化嵌套循環N-1次。它會產生最內層循環的值。

直截了當的方式做fxn('01',4)是:

for i in alphabet: 
    tempresult[0] = i 
    for i in alphabet: 
     tempresult[1] = i 
     for i in alphabet: 
      tempresult[2] = i 
      for i in alphabet: 
       tempresult[3] = i 
       yield tempresult 

基本上,我這怎麼能擴展到任意長度列表或字符串,仍然可以得到每個窩循環更新相應的索引。我知道可能有一個排列功能作爲numpy的一部分,它可以做到這一點,但我一直沒有遇到過。任何意見,將不勝感激。

+0

你想'itertools.permutations()',在標準庫中,或者更可能'itertools.product('01',repeat = 4)''。 –

+0

其實,我不認爲'numpy'有一個簡單的方法來做到這一點。您可以使用遞歸函數,在每個遞歸步驟中結合'tile'和'repeat',但這看起來不是很簡單或高效。 – abarnert

回答

3

你實際上並不想在這裏排列,而是alphabet*alphabet*alphabet*alphabet的笛卡爾積。您可以寫爲:

itertools.product(alphabet, repeat=4) 

或者,如果你想獲得字符串後面,而不是元組:

map(''.join, itertools.product(alphabet, repeat=4)) 

(在2.x中,如果你想這回一個懶惰的迭代器,而不是一個列表,你原來的代碼呢,用itertools.imap代替map。)


如果你想與numpy的做到這一點,我能想到的最好的辦法是使用遞歸函數瓷磚和重複每一個因素,但this answer有一個更好的實現,你可以從那裏複製或明顯拉出來scikit-learnsklearn.utils.extmath.cartesian,然後只是這樣做:

cartesian([alphabet]*4) 

當然,讓你一個2D單數字符串陣列;你仍然需要再一步將它壓扁成一個N位數字串的一維數組,而numpy會讓你的速度慢下來,而不是在產品計算中加快速度,所以......除非你實際上需要一個numpy數組, d堅持itertools這裏。