2011-09-03 124 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):