在c#中定义的集合是没法在lua中用for ..in ipairs()这种方法来遍历的,下面介绍一个自定义的实现来实现
Lua 迭代器
迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。
在 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
多状态的迭代器
很多情况下,迭代器需要保存多个状态信息而不是简单的状态常量和控制变量,最简单的方法是使用闭包,还有一种方法就是将所有的状态信息封装到 table 内,将 table 作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在 table 内,所以迭代函数通常不需要第二个参数
如下,自定义实现一个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