优化嵌套循环的方法通常取决于具体的情况,但有几种常见的技巧可以尝试。尽可能减少内部循环的迭代次数,这可以通过更有效的算法或数据结构来实现。如果内部循环中使用的值在外部循环中已经计算过,可以尝试在外部循环中计算并将结果存储起来,避免重复计算。下面是一个简单的示例,演示了如何通过优化来减少嵌套循环的计算量:
1、问题背景
在优化以下两个嵌套循环时遇到了一些困难:
def startbars(query_name, commodity_name):global h_listnc, s, h_list = [], {}, {}query = """ SELECT wbcode, Year, """+query_name+""" FROM innovotable WHERE commodity='"""+commodity_name+"""' and"""+query_name+""" != 'NULL' """rows = cursor.execute(query)for row in rows:n = float(row[2])s[str(row[0])+str(row[1])] = nnc.append(n)for iso in result:try:for an_year in xrange(1961, 2031, 1):skey = iso+str(an_year)h_list[skey] = 8.0 / max(nc) * s[skey]except:pass
希望找到一些优化思路来提高代码效率。
2、解决方案
优化建议:
-
将内部循环从外部循环中分离出来。因为内部循环并不依赖于外部循环,因此可以将其提取出来,这将简化代码结构并提高效率。
-
将
max(nc)
移出循环。max(nc)
在第一次循环后就是一个常量,因此可以将其移出循环以减少重复计算。 -
重新组织数据结构。优化后的代码使用了一个字典
mapYearToWbcodeToField
来存储数据,这使得查找更加高效。同时使用了一个列表nc
来存储所有值的最大值,这样就可以在一次循环中计算出constant
。
以下是优化后的代码:
def startbars(query_name, commodity_name):assert query_name in INNOVOTABLE_FIELD_NAMES## TODO: Replace with proper SQL queryquery = """ SELECT wbcode, Year, """+query_name+""" FROM innovotable WHERE commodity='"""+commodity_name+"""' and"""+query_name+""" != 'NULL' """rows = cursor.execute(query)mapYearToWbcodeToField = {}nc = []global h_listh_list = {}for row in rows:n = float(row[2])wbCodeToField = mapYearToWbcodeToField.setdefault(int(row[1]),{})wbCodeToField[str(row[0])] = nnc.append(n)constant = 8.0 / max(nc)for (an_year,wbCodeToField) in mapYearToWbcodeToField.iteritems():if an_year < 1961 or an_year > 2031:continuefor (wbCode,value) in wbCodeToField.iteritems():if wbCode not in result:continueskey = wbCode+str(an_year)h_list[skey] = constant * value
或者,还可以将所有的检查都移到第一个循环中:
def startbars(query_name, commodity_name):assert query_name in INNOVOTABLE_FIELD_NAMES## TODO: Replace with proper SQL queryquery = """ SELECT wbcode, Year, """+query_name+""" FROM innovotable WHERE commodity='"""+commodity_name+"""' and"""+query_name+""" != 'NULL' """rows = cursor.execute(query)data = []maxField = Nonefor row in rows:an_year = int(row[1])if an_year < 1961 or an_year > 2031:continuewbCode = str(row[0])if wbCode not in result:continuen = float(row[2])data.append((wbCode+str(an_year),n))if maxField is None or n > maxField:maxField = nconstant = 8.0 / maxFieldglobal h_listh_list = {}for (skey,n) in data:h_list[skey] = constant * n
在这个示例中,原始的嵌套循环遍历了二维数组中的所有元素,并将每个元素乘以2后添加到结果列表中。优化后的版本避免了使用range(len(data))
和range(len(data[i]))
来遍历索引,而是直接遍历了二维数组中的每个元素。这种优化减少了重复计算,并使代码更简洁易读。