Lua 迭代器基礎概念
Lua 迭代器是一種允許遍歷集合(如數組、表)元素的機制。迭代器通常由兩個部分組成:迭代函數和狀態控制變量。每次調用迭代函數會返回集合中的下一個元素。
泛型 for 循環
Lua 提供了泛型 for
循環來簡化迭代器的使用。語法如下:
for var1, var2, ..., varN in iterator_function, state, initial_value do-- 循環體
end
iterator_function
:迭代函數,每次調用返回下一個值。state
:迭代器的狀態(通常是集合本身)。initial_value
:迭代的初始值(通常為 nil)。
無狀態迭代器
無狀態迭代器不保留任何狀態信息,狀態完全由外部控制。典型的例子是 ipairs
和 pairs
。
warring:
同:都是能遍歷集合(表、數組)
異:ipairs 僅僅遍歷值,按照索引升序遍歷,索引中斷停止遍歷。即不能返回 nil,只能返回數字 0,如果遇到 nil 則退出。它只能遍歷到集合中出現的第一個不是整數的 key。
pairs 能遍歷集合的所有元素。即 pairs 可以遍歷集合中所有的 key,并且除了迭代器本身以及遍歷表本身還可以返回 nil。
示例:實現類似 ipairs
的迭代器
local function iter(t, i)i = i + 1if t[i] thenreturn i, t[i]end
endfunction my_ipairs(t)return iter, t, 0
end-- 使用
local arr = {10, 20, 30}
for i, v in my_ipairs(arr) doprint(i, v)
end
有狀態迭代器
有狀態迭代器將狀態封裝在閉包或表中,無需外部傳遞狀態。
閉包實現
function my_iter(t)local i = 0return function()i = i + 1if t[i] thenreturn i, t[i]endend
end-- 使用
local arr = {10, 20, 30}
for i, v in my_iter(arr) doprint(i, v)
end
表實現
local iterator = {}
iterator.__index = iteratorfunction iterator.new(t)return setmetatable({t = t, i = 0}, iterator)
endfunction iterator:__call()self.i = self.i + 1if self.t[self.i] thenreturn self.i, self.t[self.i]end
end-- 使用
local arr = {10, 20, 30}
for i, v in iterator.new(arr) doprint(i, v)
end
自定義迭代器
通過實現 __pairs
或 __ipairs
元方法,可以自定義表的迭代行為。
示例:逆序遍歷數組
local function reverse_iter(t, i)i = i - 1if i > 0 thenreturn i, t[i]end
endfunction reverse_ipairs(t)return reverse_iter, t, #t + 1
end-- 使用
local arr = {10, 20, 30}
for i, v in reverse_ipairs(arr) doprint(i, v)
end
協程迭代器
協程可以用于實現復雜的迭代邏輯,尤其是需要跨多次調用維護狀態的情況。
示例:遍歷二叉樹
local function traverse(node)if not node then return endtraverse(node.left)coroutine.yield(node.value)traverse(node.right)
endfunction tree_iter(root)return coroutine.wrap(function()traverse(root)end)
end-- 使用
local tree = {value = 2,left = {value = 1},right = {value = 3}
}
for v in tree_iter(tree) doprint(v) -- 輸出 1, 2, 3
end
性能優化建議
- 無狀態迭代器通常比有狀態迭代器更快,因為避免了閉包創建的開銷。
- 對于大規模數據,優先使用
ipairs
或pairs
而不是自定義迭代器。 - 協程迭代器雖然靈活,但會有額外的協程調度開銷。