迭代器(iterator)是一種對象,它能夠用來遍歷標準模板庫容器中的部分或全部元素,每個迭代器對象代表容器中的確定的地址。
在 Lua 中迭代器是一種支持指針類型的結構,它可以遍歷集合的每一個元素。
泛型 for 在自己內(nèi)部保存迭代函數(shù),實際上它保存三個值:迭代函數(shù)、狀態(tài)常量、控制變量。
泛型 for 迭代器提供了集合的 key/value 對,語法格式如下:
for k, v in pairs(t) do print(k, v) end
上面代碼中,k, v為變量列表;pairs(t)為表達式列表。
查看以下示例:
array = {"Google", "Nhooo"} for key,value in ipairs(array) do print(key, value) end
以上代碼執(zhí)行輸出結果為:
1 Google 2 Nhooo
以上示例中我們使用了 Lua 默認提供的迭代函數(shù) ipairs。
下面我們看看泛型 for 的執(zhí)行過程:
首先,初始化,計算 in 后面表達式的值,表達式應該返回泛型 for 需要的三個值:迭代函數(shù)、狀態(tài)常量、控制變量;與多值賦值一樣,如果表達式返回的結果個數(shù)不足三個會自動用 nil 補足,多出部分會被忽略。
第二,將狀態(tài)常量和控制變量作為參數(shù)調(diào)用迭代函數(shù)(注意:對于 for 結構來說,狀態(tài)常量沒有用處,僅僅在初始化時獲取他的值并傳遞給迭代函數(shù))。
第三,將迭代函數(shù)返回的值賦給變量列表。
第四,如果返回的第一個值為nil循環(huán)結束,否則執(zhí)行循環(huán)體。
第五,回到第二步再次調(diào)用迭代函數(shù)
在Lua中我們常常使用函數(shù)來描述迭代器,每次調(diào)用該函數(shù)就返回集合的下一個元素。Lua 的迭代器包含以下兩種類型:
無狀態(tài)的迭代器
多狀態(tài)的迭代器
無狀態(tài)的迭代器是指不保留任何狀態(tài)的迭代器,因此在循環(huán)中我們可以利用無狀態(tài)迭代器避免創(chuàng)建閉包花費額外的代價。
每一次迭代,迭代函數(shù)都是用兩個變量(狀態(tài)常量和控制變量)的值作為參數(shù)被調(diào)用,一個無狀態(tài)的迭代器只利用這兩個值可以獲取下一個元素。
這種無狀態(tài)迭代器的典型的簡單的實例是 ipairs,它遍歷數(shù)組的每一個元素。
以下示例我們使用了一個簡單的函數(shù)來實現(xiàn)迭代器,實現(xiàn) 數(shù)字 n 的平方:
function square(iteratorMaxCount,currentNumber) if currentNumber<iteratorMaxCount then currentNumber = currentNumber+1 return currentNumber, currentNumber*currentNumber end end for i,n in square,3,0 do print(i,n) end
以上示例輸出結果為:
1 1 2 4 3 9
迭代的狀態(tài)包括被遍歷的表(循環(huán)過程中不會改變的狀態(tài)常量)和當前的索引下標(控制變量),ipairs 和迭代函數(shù)都很簡單,我們在 Lua 中可以這樣實現(xiàn):
function iter (a, i) i = i + 1 local v = a[i] if v then return i, v end end function ipairs (a) return iter, a, 0 end
當 Lua 調(diào)用 ipairs(a) 開始循環(huán)時,他獲取三個值:迭代函數(shù) iter、狀態(tài)常量 a、控制變量初始值 0;然后 Lua 調(diào)用 iter(a,0) 返回 1, a[1](除非 a[1]=nil);第二次迭代調(diào)用 iter(a,1) 返回 2, a[2]……直到第一個 nil 元素。
很多情況下,迭代器需要保存多個狀態(tài)信息而不是簡單的狀態(tài)常量和控制變量,最簡單的方法是使用閉包,還有一種方法就是將所有的狀態(tài)信息封裝到 table 內(nèi),將 table 作為迭代器的狀態(tài)常量,因為這種情況下可以將所有的信息存放在 table 內(nèi),所以迭代函數(shù)通常不需要第二個參數(shù)。
以下示例我們創(chuàng)建了自己的迭代器:
array = {"Google", "Nhooo"} function elementIterator (collection) local index = 0 local count = #collection -- 閉包函數(shù) return function () index = index + 1 if index <= count then -- 返回迭代器的當前元素 return collection[index] end end end for element in elementIterator(array) do print(element) end
以上示例輸出結果為:
Google Nhooo
以上示例中我們可以看到,elementIterator 內(nèi)使用了閉包函數(shù),實現(xiàn)計算集合大小并輸出各個元素。