2017-03-16 48 views
0

我们有一个使用itertools.combinations()的脚本,它似乎挂起的输入大小很大。Python的超时问题itertools.combinations()

我是一个相对缺乏经验的Python程序员,所以我不知道如何解决这个问题。有更合适的图书馆吗?或者有没有办法启用详细日志记录,我可以调试为什么方法调用挂起?

任何帮助,非常感谢。

[编辑]

def findsubsets(S,m): 
    return set(itertools.combinations(S, m)) 

for s in AllSearchTerms: 
    S.append(itemsize) 
    itemsize = itemsize + 1 

for i in range (1,6): 
    Subset = findsubsets(S,i) 
    for sub in Subset: 
     for s in sub: 
      sublist.append(AllSearchTerms[s]) 
     PComb.append(sublist) 
     sublist = [] 
+5

'itertools.combinations(..)'本身是** lazy **。因此,它取决于**消费者对输出**做了什么...... –

+2

正如前面的评论所述,结果取决于你对来自'itertools.combinations()'的返回值做了什么。如果您需要更多帮助,请向我们展示一个代码片段,其中显示您对结果和结果挂起的操作。请参见[如何创建最小,完整和可验证示例](http://stackoverflow.com/help/mcve)。 –

+0

此外,您的算法的组合数量[可能是_huge; _](https://en.wikipedia.org/wiki/Binomial_coefficient#Binomial_coefficients_as_polynomials)可能是正确的,只是工作时间超出您的预期。 – 9000

回答

0

你在你的代码的两件事情,将挂于大尺寸的输入。

首先,您的函数findsubsets调用itertools.combinations然后将结果转换为集合。 itertools.combinations的结果是一个生成器,每次生成一个组合,而不存储它们或一次全部计算它们。当你将它转换为一个集合时,你可以强制Python计算并一次存储它们。因此,行return set(itertools.combinations(S, m))几乎可以肯定你的程序挂起的地方。您可以通过在该行之前和之后立即放置打印语句(或其他类型的日志语句)来检查该情况,并且如果看到前面的打印并且程序在看到后续打印之前挂起,则会发现问题。解决方案不是将组合转换为集合。将其作为生成器保存,并且您的程序可以根据需要一次抓取一个组合。第二,即使你按我刚刚建议的做法,你的循环for sub in Subset:是一个相当紧密的循环,它使用每一种组合。如果输入规模很大,那么这个循环将需要很长时间,并且执行我之前的段落也无济于事。你可能应该重新组织你的程序以避免大的输入大小,或者至少在循环中显示某种进展。组合功能has a predictable output size,所以你甚至可以显示进度条中完成的百分比。

itertools.combinations内部没有记录,因为正确使用时不需要记录,并且在将发生器转换为集合时没有记录。如果需要,您可以在自己的紧密循环中实现日志记录。

+0

Thanks @Rory。是的,你是完全正确的 - 我已经把日志声明,并可以确认'返回集(itertools.combinations(S,m))'是它挂起的地方。我会尝试你的建议解决方案,看看它是否解决了这个问题。我会测试这个和upvote如果它的作品:) –