1. 程式人生 > >lua 10 迭代器

lua 10 迭代器

轉自:http://www.runoob.com/lua/lua-iterators.html

 

迭代器(iterator)是一種物件,它能夠用來遍歷標準模板庫容器中的部分或全部元素,每個迭代器物件代表容器中的確定的地址

在Lua中迭代器是一種支援指標型別的結構,它可以遍歷集合的每一個元素。


泛型 for 迭代器

泛型 for 在自己內部儲存迭代函式,實際上它儲存三個值:迭代函式、狀態常量、控制變數。

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

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

  

上面程式碼中,k, v為變數列表;pairs(t)為表示式列表。

檢視以下例項:

array = {"Lua", "Tutorial"}

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

  

以上程式碼執行輸出結果為:

1  Lua
2  Tutorial

  

以上例項中我們使用了 Lua 預設提供的迭代函式 ipairs。

下面我們看看泛型 for 的執行過程:

  • 首先,初始化,計算in後面表示式的值,表示式應該返回泛型 for 需要的三個值:迭代函式、狀態常量、控制變數;與多值賦值一樣,如果表示式返回的結果個數不足三個會自動用nil補足,多出部分會被忽略。
  • 第二,將狀態常量和控制變數作為引數呼叫迭代函式(注意:對於for結構來說,狀態常量沒有用處,僅僅在初始化時獲取他的值並傳遞給迭代函式)。
  • 第三,將迭代函式返回的值賦給變數列表。
  • 第四,如果返回的第一個值為nil迴圈結束,否則執行迴圈體。
  • 第五,回到第二步再次呼叫迭代函式

在Lua中我們常常使用函式來描述迭代器,每次呼叫該函式就返回集合的下一個元素。Lua 的迭代器包含以下兩種型別:

  • 無狀態的迭代器
  • 多狀態的迭代器

無狀態的迭代器

無狀態的迭代器是指不保留任何狀態的迭代器,因此在迴圈中我們可以利用無狀態迭代器避免建立閉包花費額外的代價。

每一次迭代,迭代函式都是用兩個變數(狀態常量和控制變數)的值作為引數被呼叫

,一個無狀態的迭代器只利用這兩個值可以獲取下一個元素。

這種無狀態迭代器的典型的簡單的例子是ipairs,它遍歷陣列的每一個元素。

以下例項我們使用了一個簡單的函式來實現迭代器,實現 數字 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

  

迭代的狀態包括被遍歷的表(迴圈過程中不會改變的狀態常量)和當前的索引下標(控制變數),ipairs和迭代函式都很簡單,我們在Lua中可以這樣實現:

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呼叫ipairs(a)開始迴圈時,他獲取三個值:迭代函式iter、狀態常量a、控制變數初始值0;然後Lua呼叫iter(a,0)返回1,a[1](除非a[1]=nil);第二次迭代呼叫iter(a,1)返回2,a[2]……直到第一個nil元素。


多狀態的迭代器

很多情況下,迭代器需要儲存多個狀態資訊而不是簡單的狀態常量和控制變數,最簡單的方法是使用閉包,還有一種方法就是將所有的狀態資訊封裝到table內,將table作為迭代器的狀態常量,因為這種情況下可以將所有的資訊存放在table內,所以迭代函式通常不需要第二個引數。

 

以下例項我們建立了自己的迭代器:

array = {"Lua", "Tutorial"}

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

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

  

以上例項輸出結果為:

Lua
Tutorial

  

以上例項中我們可以看到,elementIterator 內使用了閉包函式,實現計算集合大小並輸出各個元素。