我试图查看嵌套字典中有多少值< =一个值(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])
我可以对此进行修改以显着加快速度吗?我是否应该完全取消使用字典而支持另一种更适合的数据结构?任何想法都非常感激。
答案 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
中。如果它的值是无法检查成员身份的容器(例如列表),则最后一个条件将很慢。您可以使用set
或dict
来加快速度,因为这些类型具有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])