从嵌套字典中快速完成条件求和的方法?

时间:2018-01-14 22:05:14

标签: python python-3.x

我试图查看嵌套字典中有多少值< =一个值(rcEnterThreshold),但要受其他简单条件的影响。嵌套字典有大约1000万个值,大约需要30秒才能执行以下操作:

numCandidateVars = sum(1 for f in reducedCosts 
                         for t in reducedCosts[f] 
                       if f!=t if reducedCosts[f][t][colGenLoopCounter] <= rcEnterThreshold 
                       if t not in EdgeDict[f])

我可以对此进行修改以显着加快速度吗?我是否应该完全取消使用字典而支持另一种更适合的数据结构?任何想法都非常感激。

2 个答案:

答案 0 :(得分:1)

通过迭代嵌套字典的items(),您可能会获得一些加速,而不是每次只获取密钥并为其编制索引。我怀疑加速会很大,因为索引是O(1),但它可能有所帮助。

numCandidateVars = sum(1 for f, middle in reducedCosts.items() 
                         for t, inner in middle.items()
                         if f!=t
                         if inner[colGenLoopCounter] <= rcEnterThreshold 
                         if t not in EdgeDict[f])

我也回应Turksarama,在单个生成器表达式中包含许多if子句似乎非常奇怪。我已经使用Python多年了,在阅读你的代码之前我一直都不知道这样的事情是合法的!如果您使用if连接它们,则单个and可以测试多个条件。不幸的是,切换到使用and可能不会加速(或者根本)加速事情,因为似乎多个if子句以与and完全相同的方式短路。

重新排序您的条件可能有助于提高绩效,但由于您还没有告诉我们任何有关数据性质的信息,我们无法判断哪些测试会比其他。我猜测关键测试f != t很快,但如果这些是复杂的类型,即使这可能也不是真的。我猜这个订单是你能做的最好的。

您可以加快速度的另一个地方实际上并不在您已经展示的代码中,而是在EdgeDict中。如果它的值是无法检查成员身份的容器(例如列表),则最后一个条件将很慢。您可以使用setdict来加快速度,因为这些类型具有O(1)成员资格测试。如果EdgeDict的值已经是这些类型的值,那么我不会有任何进一步的建议,除了可能分析代码并查看实际花费最多时间的步骤。

答案 1 :(得分:0)

你正在寻找一个长度,所以尝试len()而不是sum(),但除此之外我们可能无法帮助你解决你的信息&# 39;给了我们。什么数据类型是f?如果它是整数,则列表可能更快。什么是colGenLoopCounter?尝试使用带有ands的一个if语句,最先使用一个失败的语句。这应该让你捷径。

示例:

numCandidateVars = sum(1 for f in reducedCosts 
                       for t in reducedCosts[f] 
                       if f!=t # this is suspicious, why is it here?
                       and reducedCosts[f][t][colGenLoopCounter] <= rcEnterThreshold 
                       and t not in EdgeDict[f])