# Lua 迭代器
迭代器(iterator)是一種對象,它能夠用來遍歷標準模板庫容器中的部分或全部元素,每個迭代器對象代表容器中的確定的地址
在Lua中迭代器是一種支持指針類型的結構,它可以遍歷集合的每一個元素。
### 泛型 for 迭代器
泛型 for 在自己內部保存迭代函數,實際上它保存三個值:迭代函數、狀態常量、控制變量。
泛型 for 迭代器提供了集合的 key/value 對,語法格式如下:
~~~
~~~
for?k,?v?in?pairs(t)?do
????print(k,?v)
end
~~~
~~~
上面代碼中,k, v為變量列表;pair(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 內使用了閉包函數,實現計算集合大小并輸出各個元素。
- Lua 簡介
- Lua 環境安裝
- Lua 數據類型
- Lua 變量
- Lua 循環
- Lua while 循環
- Lua for 循環
- Lua repeat...until 循環
- Lua 循環嵌套
- Lua break 語句
- Lua 流程控制
- Lua if 語句
- Lua if...else 語句
- Lua if 嵌套語句
- Lua 函數
- Lua 運算符
- Lua 字符串
- Lua 數組
- Lua 迭代器
- Lua table(表)
- Lua 模塊與包
- Lua 元表(Metatable)
- Lua 協同程序(coroutine)
- Lua 文件 I/O
- Lua 錯誤處理
- Lua 調試(Debug)
- Lua 垃圾回收
- Lua 面向對象
- Lua 數據庫訪問
- CoverPage