优化两个简单的嵌套循环

2024-04-15 10:51:21 浏览数 (2)

优化嵌套循环的方法通常取决于具体的情况,但有几种常见的技巧可以尝试。尽可能减少内部循环的迭代次数,这可以通过更有效的算法或数据结构来实现。如果内部循环中使用的值在外部循环中已经计算过,可以尝试在外部循环中计算并将结果存储起来,避免重复计算。下面是一个简单的示例,演示了如何通过优化来减少嵌套循环的计算量:

1、问题背景

在优化以下两个嵌套循环时遇到了一些困难:

代码语言:javascript复制
def startbars(query_name, commodity_name):
​
    global h_list
    nc, 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])] = n
        nc.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、解决方案

优化建议:

  1. 将内部循环从外部循环中分离出来。因为内部循环并不依赖于外部循环,因此可以将其提取出来,这将简化代码结构并提高效率。
  2. max(nc)移出循环。max(nc)在第一次循环后就是一个常量,因此可以将其移出循环以减少重复计算。
  3. 重新组织数据结构。优化后的代码使用了一个字典mapYearToWbcodeToField来存储数据,这使得查找更加高效。同时使用了一个列表nc来存储所有值的最大值,这样就可以在一次循环中计算出constant

以下是优化后的代码:

代码语言:javascript复制
def startbars(query_name, commodity_name):
​
    assert query_name in INNOVOTABLE_FIELD_NAMES
​
    ## TODO: Replace with proper SQL query
    query = """ SELECT wbcode, Year, """ query_name """ 
             FROM innovotable WHERE commodity='""" commodity_name """' and
​
             """ query_name """ != 'NULL' """
    rows = cursor.execute(query)
​
    mapYearToWbcodeToField = {}
    nc = []
    global h_list
    h_list = {}
​
    for row in rows:
        n = float(row[2])
        wbCodeToField = mapYearToWbcodeToField.setdefault(int(row[1]),{})
        wbCodeToField[str(row[0])] = n
        nc.append(n)
​
    constant = 8.0 / max(nc)
​
​
    for (an_year,wbCodeToField) in mapYearToWbcodeToField.iteritems():
        if an_year < 1961 or an_year > 2031:
            continue
​
        for (wbCode,value) in wbCodeToField.iteritems():
            if wbCode not in result:
                continue
​
            skey = wbCode str(an_year)
            h_list[skey] = constant * value
​

或者,还可以将所有的检查都移到第一个循环中:

代码语言:javascript复制
def startbars(query_name, commodity_name):
​
    assert query_name in INNOVOTABLE_FIELD_NAMES
​
    ## TODO: Replace with proper SQL query
    query = """ SELECT wbcode, Year, """ query_name """ 
             FROM innovotable WHERE commodity='""" commodity_name """' and
​
             """ query_name """ != 'NULL' """
    rows = cursor.execute(query)
​
    data = []
    maxField = None
​
    for row in rows:
        an_year = int(row[1])
        if an_year < 1961 or an_year > 2031:
            continue
​
        wbCode = str(row[0])
        if wbCode not in result:
            continue
​
        n = float(row[2])
​
        data.append((wbCode str(an_year),n))
        if maxField is None or n > maxField:
            maxField = n
​
    constant = 8.0 / maxField
​
    global h_list
    h_list = {}
​
    for (skey,n) in data:
        h_list[skey] = constant * n

在这个示例中,原始的嵌套循环遍历了二维数组中的所有元素,并将每个元素乘以2后添加到结果列表中。优化后的版本避免了使用range(len(data))range(len(data[i]))来遍历索引,而是直接遍历了二维数组中的每个元素。这种优化减少了重复计算,并使代码更简洁易读。

0 人点赞