Lua 迭代器

2022-01-29 10:32 更新

迭代器(iterator)是一種對(duì)象,它能夠用來(lái)遍歷標(biāo)準(zhǔn)模板庫(kù)容器中的部分或全部元素,每個(gè)迭代器對(duì)象代表容器中的確定的地址

在Lua中迭代器是一種支持指針類型的結(jié)構(gòu),它可以遍歷集合的每一個(gè)元素。


泛型 for 迭代器

泛型 for 在自己內(nèi)部保存迭代函數(shù),實(shí)際上它保存三個(gè)值:迭代函數(shù)、狀態(tài)常量、控制變量。

泛型 for 迭代器提供了集合的 key/value 對(duì),語(yǔ)法格式如下:

for k, v in pairs(t) do
    print(k, v)
end

上面代碼中,k, v為變量列表;pairs(t)為表達(dá)式列表。

查看以下實(shí)例:

array = {"Lua", "Tutorial"}

for key,value in ipairs(array) 
do
   print(key, value)
end

以上代碼執(zhí)行輸出結(jié)果為:

1  Lua
2  Tutorial

以上實(shí)例中我們使用了 Lua 默認(rèn)提供的迭代函數(shù) ipairs。

下面我們看看范性for的執(zhí)行過(guò)程:

  • 首先,初始化,計(jì)算in后面表達(dá)式的值,表達(dá)式應(yīng)該返回范性for需要的三個(gè)值:迭代函數(shù)、狀態(tài)常量、控制變量;與多值賦值一樣,如果表達(dá)式返回的結(jié)果個(gè)數(shù)不足三個(gè)會(huì)自動(dòng)用nil補(bǔ)足,多出部分會(huì)被忽略。
  • 第二,將狀態(tài)常量和控制變量作為參數(shù)調(diào)用迭代函數(shù)(注意:對(duì)于for結(jié)構(gòu)來(lái)說(shuō),狀態(tài)常量沒(méi)有用處,僅僅在初始化時(shí)獲取他的值并傳遞給迭代函數(shù))。
  • 第三,將迭代函數(shù)返回的值賦給變量列表。
  • 第四,如果返回的第一個(gè)值為nil循環(huán)結(jié)束,否則執(zhí)行循環(huán)體。
  • 第五,回到第二步再次調(diào)用迭代函數(shù)

。在Lua中我們常常使用函數(shù)來(lái)描述迭代器,每次調(diào)用該函數(shù)就返回集合的下一個(gè)元素。Lua 的迭代器包含以下兩種類型:

  • 無(wú)狀態(tài)的迭代器
  • 多狀態(tài)的迭代器

無(wú)狀態(tài)的迭代器

無(wú)狀態(tài)的迭代器是指不保留任何狀態(tài)的迭代器,因此在循環(huán)中我們可以利用無(wú)狀態(tài)迭代器避免創(chuàng)建閉包花費(fèi)額外的代價(jià)。

每一次迭代,迭代函數(shù)都是用兩個(gè)變量(狀態(tài)常量和控制變量)的值作為參數(shù)被調(diào)用,一個(gè)無(wú)狀態(tài)的迭代器只利用這兩個(gè)值可以獲取下一個(gè)元素。

這種無(wú)狀態(tài)迭代器的典型的簡(jiǎn)單的例子是ipairs,他遍歷數(shù)組的每一個(gè)元素。

以下實(shí)例我們使用了一個(gè)簡(jiǎn)單的函數(shù)來(lái)實(shí)現(xiàn)迭代器,實(shí)現(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

以上實(shí)例輸出結(jié)果為:

1	1
2	4
3	9

迭代的狀態(tài)包括被遍歷的表(循環(huán)過(guò)程中不會(huì)改變的狀態(tài)常量)和當(dāng)前的索引下標(biāo)(控制變量),ipairs和迭代函數(shù)都很簡(jiǎn)單,我們?cè)贚ua中可以這樣實(shí)現(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

當(dāng)Lua調(diào)用ipairs(a)開(kāi)始循環(huán)時(shí),他獲取三個(gè)值:迭代函數(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]……直到第一個(gè)nil元素。


多狀態(tài)的迭代器

很多情況下,迭代器需要保存多個(gè)狀態(tài)信息而不是簡(jiǎn)單的狀態(tài)常量和控制變量,最簡(jiǎn)單的方法是使用閉包,還有一種方法就是將所有的狀態(tài)信息封裝到table內(nèi),將table作為迭代器的狀態(tài)常量,因?yàn)檫@種情況下可以將所有的信息存放在table內(nèi),所以迭代函數(shù)通常不需要第二個(gè)參數(shù)。

以下實(shí)例我們創(chuàng)建了自己的迭代器:

array = {"Lua", "Tutorial"}

function elementIterator (collection)
   local index = 0
   local count = #collection
   -- 閉包函數(shù)
   return function ()
      index = index + 1
      if index <= count
      then
         --  返回迭代器的當(dāng)前元素
         return collection[index]
      end
   end
end

for element in elementIterator(array)
do
   print(element)
end

以上實(shí)例輸出結(jié)果為:

Lua
Tutorial

以上實(shí)例中我們可以看到,elementIterator 內(nèi)使用了閉包函數(shù),實(shí)現(xiàn)計(jì)算集合大小并輸出各個(gè)元素。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)