2011-09-03 66 views
3

我試圖創建一個生成器函數中:幫助與邏輯發生器功能

def combinations(iterable, r, maxGapSize): 
    maxGapSizePlusOne = maxGapSize+1 

    pool = tuple(iterable) 
    n = len(pool) 
    if r > n: 
     return 
    indices = list(range(r)) 

    while True: 
     for i in reversed(range(r)):   
      if indices[i] != i + n - r:  
       break 
     else: 
      return 

     indices[i] += 1 
     for j in range(i+1, r): 
      indices[j] = indices[j-1] + 1 

     previous = indices[0] 
     for k in indices[1:]: 
      if k-previous>maxGapSizePlusOne: 
       isGapTooBig = True 
       break 
      previous = k 
     else: 
      isGapTooBig = False 

     if not isGapTooBig: 
      print(indices) 


combinations(("Aa","Bbb","Ccccc","Dd","E","Ffff",),2,1) 

我打印出來,我想用它來選擇所謂的「迭代」的說法元素的索引調試目的。這給了我:

 
[0, 2] 
[1, 2] 
[1, 3] 
[2, 3] 
[2, 4] 
[3, 4] 
[3, 5] 
[4, 5] 

,因爲這是其他地方生產的忽略[0,1] ...

這正是我想要的,但我猜我的代碼,它過於複雜,效率低下。 iterable的大小很可能是成千上萬,而且很可能是maxGapSize < 5

任何提示,以幫助我做得更好?

+0

你沒有解釋它應該做什麼。 – agf

+0

如果您的代碼已經正常工作,但您希望使其更好,則可以在http://codereview.stackexchange.com/查詢。 –

回答

3

您的許多代碼看起來與Python code for itertools.combination完全一樣。 CPython實現itertools.combination用C編寫。鏈接到上面的文檔顯示了與Python等效的代碼。

可以通過簡單地使用itertools.combination而不是使用Python的等效代碼加快功能:

import itertools as it 
def mycombinations(iterable, r, maxGapSize): 
    maxGapSizePlusOne = maxGapSize+1  
    for indices in it.combinations(range(len(iterable)),r): 
     previous = indices[0] 
     for k in indices[1:]: 
      if k-previous>maxGapSizePlusOne:      
       break 
      previous = k 
     else: 
      yield indices 
      # print(indices) 

可以使用timeit到這種方式比較替代實施方式中的相對速度:

原始版本:

% python -mtimeit -s'import test' 'list(test.combinations(("Aa","Bbb","Ccccc","Dd","E","Ffff",),2,1))' 
10000 loops, best of 3: 63.9 usec per loop 

使用itertools.combination:

% python -mtimeit -s'import test' 'list(test.mycombinations(("Aa","Bbb","Ccccc","Dd","E","Ffff",),2,1))' 
100000 loops, best of 3: 17.2 usec per loop 

上面代碼的所有組合,包括初始組合,range(len(iterable))。我認爲離開這種方式更美麗。但如果你真的要刪除的第一組合,你可以使用

def mycombinations(iterable, r, maxGapSize): 
    ... 
    comb=it.combinations(range(len(iterable)),r) 
    next(comb) 
    for indices in comb: 

順便說一句,該功能combinations並不真正依賴於iterable。它僅取決於iterable的長度。因此,最好是撥打電話簽名

def combinations(length, r, maxGapSize):