在c#中定義的集合是沒法在lua中用for ..in ipairs()這種方法來遍歷的九杂,下面介紹一個自定義的實現(xiàn)來實現(xiàn)
Lua 迭代器
迭代器(iterator)是一種對象剪决,它能夠用來遍歷標準模板庫容器中的部分或全部元素梢薪,每個迭代器對象代表容器中的確定的地址耻讽。
在 Lua 中迭代器是一種支持指針類型的結構有决,它可以遍歷集合的每一個元素
無狀態(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
多狀態(tài)的迭代器
很多情況下,迭代器需要保存多個狀態(tài)信息而不是簡單的狀態(tài)常量和控制變量达罗,最簡單的方法是使用閉包坝撑,還有一種方法就是將所有的狀態(tài)信息封裝到 table 內(nèi),將 table 作為迭代器的狀態(tài)常量粮揉,因為這種情況下可以將所有的信息存放在 table 內(nèi)巡李,所以迭代函數(shù)通常不需要第二個參數(shù)
如下,自定義實現(xiàn)一個ipairs一樣功能的迭代器
function kpairs(t)
? ? local index = 0
? ? local count = #t
? ? return function ()
? ? ? ? index = index + 1
? ? ? ? if index <= count then
? ? ? ? ? ? local v = t[index]
? ? ? ? ? ? if v then
? ? ? ? ? ? ? ? return index, v
? ? ? ? ? ? else
? ? ? ? ? ? ? ? return nil
? ? ? ? ? ? end
? ? ? ? end
? end
end
for i, v in kpairs(a) do
? ? print(string.format("%s=%s", i, tostring(v)))
end
如果不判斷空的話扶认,上例將輸出所有元素侨拦,包括nil,而我們知道ipairs是遇到nil就認為遍歷結束了
有了這些基礎之后,再來看怎么自定義一個遍歷c#集合的迭代器辐宾,假設list在c#中是這樣申明的
class MyItem{
? ? public string name;
? ? public int value;
}
var list = new List<MyItem>();
function xpairs(list)
? ? if list then
? ? ? ? local iter = list:GetEnumerator()
? ? ? ? return function()
? ? ? ? ? ? if iter:MoveNext() then
? ? ? ? ? ? ? ? return iter.Current
? ? ? ? ? ? else
? ? ? ? ? ? ? ? iter:Dispose()
? ? ? ? ? ? ? ? return nil
? ? ? ? ? ? end
? ? ? ? end
? ? end
? ? return nil
end
則用法如下
for item in xpairs(list) do
? ? print(string.format("name=%s, value=%s", item.name, item.value))
end