2016-02-26 112 views
3

我想弄清楚如何遍歷任意數量的循環,其中每個循環取決於最近的外層循環。下面的代碼是什麼,我想要做的一個例子:任意數量的嵌套循環依賴於Python中的前一個循環

def function(z): 
    n = int(log(z)) 
    tupes = [] 
    for i_1 in range(1, n): 
     for i_2 in range(1, i_1): 
      ... 
       ... 
        ... 
         for i_n in range(1, i_{n - 1}): 
          if i_1*i_2*...*i_n > z: 
           tupes.append((i_1, i_2,..., i_n)) 
    return tupes 

雖然我想這對任何z>e**2的工作,它足以讓它爲z的工作達e**100。我知道,如果我採用合適的笛卡爾積,那麼最終會得到我想要的元組的超集,但我只想獲得我所尋找的元組。

如果有人能幫助我,我會非常感激。提前致謝。

+9

使用函數和遞歸。 – zondo

回答

1

在遞歸執行你的問題的邏輯(注意,這允許重複的元組):

import functools 

def f(n, z, max_depth, factors=(), depth=0): 
    res = [] 
    if depth == max_depth: 
     product = functools.reduce(lambda x, y: x*y, factors, 1) 
     if product > z: 
      res.append(factors) 
    else: 
     for i in range(1, n): 
      new_factors = factors + (i,) 
      res.extend(f(i, z, factors=new_factors, depth=depth+1, max_depth=max_depth)) 
    return res 

z = np.e ** 10 
n = int(np.log(z)) 

print(f(n, z, max_depth=8)) 

產生

[(8, 7, 6, 5, 4, 3, 2, 1), 
(9, 7, 6, 5, 4, 3, 2, 1), 
(9, 8, 6, 5, 4, 3, 2, 1), 
(9, 8, 7, 5, 4, 3, 2, 1), 
(9, 8, 7, 6, 4, 3, 2, 1), 
(9, 8, 7, 6, 5, 3, 2, 1), 
(9, 8, 7, 6, 5, 4, 2, 1), 
(9, 8, 7, 6, 5, 4, 3, 1), 
(9, 8, 7, 6, 5, 4, 3, 2)] 
+0

我很抱歉花了這麼長時間來表達我的感激之情,但顯然我的大腦不再正常工作,因爲我在我的問題和這個功能上掙扎的方式太多了。我最終需要一個稍微不同的功能,但總體佈局與此相同。非常感謝你的幫助。儘管事實上我嘗試將我所有的Python代碼重新創建爲Haskell代碼,但我仍然認爲我仍然不是遞歸方面的專家,這是令人尷尬的。 – basketballfan22

1

正如zondo建議的那樣,您需要使用函數和遞歸來完成此任務。沿着以下線的東西應該工作:

def recurse(tuplesList, potentialTupleAsList, rangeEnd, z): 
    # No range to iterate over, check if tuple sum is large enough 
    if rangeEnd = 1 and sum(potentialTupleAsList) > z: 
     tuplesList.append(tuple(potentialTupeAsList)) 
     return 
    for i in range(1, rangeEnd): 
     potentialTupleAsList.append(i) 
     recurse(tuplesList, potentialTupleAsList, rangeEnd - 1, z) 
     # Need to remove item you used to make room for new value 
     potentialTupleAsList.pop(-1) 

然後,你可以把它作爲這樣得到的結果:

l = [] 
recurse(l, [], int(log(z)), z) 
print l 
2

組合可以在升序排列;實際上,這是itertools.combinations的默認行爲。

代碼:

for i1 in range(1,6): 
    for i2 in range(1,i1): 
     for i3 in range(1,i2): 
      print (i3, i2, i1) 

# (1, 2, 3) 
# (1, 2, 4) 
# ... 
# (3, 4, 5) 

相當於代碼:

from itertools import combinations 

for combination in combinations(range(1,6), 3): 
    print combination 

# (1, 2, 3) 
# (1, 2, 4) 
# ... 
# (3, 4, 5) 

使用,而不是笛卡爾乘積組合剔除樣本空間縮小到你想要的東西。