最佳化兩個簡單的巢狀迴圈

华科云商小雪發表於2024-04-15

最佳化巢狀迴圈的方法通常取決於具體的情況,但有幾種常見的技巧可以嘗試。儘可能減少內部迴圈的迭代次數,這可以透過更有效的演算法或資料結構來實現。如果內部迴圈中使用的值在外部迴圈中已經計算過,可以嘗試在外部迴圈中計算並將結果儲存起來,避免重複計算。下面是一個簡單的示例,演示瞭如何透過最佳化來減少巢狀迴圈的計算量:

1、問題背景

在最佳化以下兩個巢狀迴圈時遇到了一些困難:


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

以下是最佳化後的程式碼:


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

或者,還可以將所有的檢查都移到第一個迴圈中:


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])) 來遍歷索引,而是直接遍歷了二維陣列中的每個元素。這種最佳化減少了重複計算,並使程式碼更簡潔易讀。


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70034537/viewspace-3012524/,如需轉載,請註明出處,否則將追究法律責任。

相關文章