Lua 迭代器
Lua - 迭代器
Section titled “Lua - 迭代器”迭代器(Iterator)是一种机制,允许你逐个遍历集合(在 Lua 中通常是 table)中的所有元素。Lua 的泛型 for 循环是使用迭代器的主要方式。
泛型 for 循环与迭代器
Section titled “泛型 for 循环与迭代器”泛型 for 循环使用一个迭代器函数来遍历集合。其语法如下:
for var_1, var_2, ..., var_n in iterator_function, state, initial_value do -- 循环体endLua 提供了两个常用的内置 table 迭代器函数:
ipairs(t): 遍历 tablet的整数键,从 1 开始直到第一个缺失的整数键为止(即用于类数组的序列)。它在每一步返回索引(键)和对应的值。pairs(t): 遍历 tablet中的所有键值对,包括非整数键和非连续的整数键。pairs的遍历顺序是不确定的。
使用 ipairs 的示例(用于序列):
local days = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"}
for index, dayName in ipairs(days) do print(index, dayName)end-- 输出:-- 1 Monday-- 2 Tuesday-- 3 Wednesday-- 4 Thursday-- 5 Friday使用 pairs 的示例(用于通用 table):
local person = { name = "Alice", age = 30, city = "New York" }person[1] = "Extra Info" -- 添加一个数字键
for key, value in pairs(person) do print(key, value)end-- 可能的输出(顺序可能不同):-- name Alice-- city New York-- 1 Extra Info-- age 30自定义迭代器
Section titled “自定义迭代器”在 Lua 中,迭代器是通过函数实现的。泛型 for 循环会重复调用这个迭代器函数。根据状态维护方式,自定义迭代器主要有两种类型:
- 无状态迭代器
- 有状态迭代器
无状态迭代器
Section titled “无状态迭代器”无状态迭代器是一个函数,在每次迭代时,它从 for 循环本身接收当前的状态和控制变量。它不需要在函数调用之间内部保存任何状态;for 循环负责管理状态。
我们来创建一个无状态迭代器,它生成直到某个限制的数字的平方。
-- 迭代器函数:square_iter(limit, current_num)-- limit: 不变状态(最大计数)-- current_num: 控制变量function square_iter(limit, current_num) current_num = current_num + 1 if current_num <= limit then return current_num, current_num * current_num -- 返回新的控制变量,值 end -- 没有更多值了,返回 nil 停止迭代end
-- 直接将无状态迭代器函数与 for 循环一起使用-- for <循环变量> in <迭代器函数>, <不变状态>, <初始控制变量> doprint("使用直接迭代器函数生成平方:")for i, n_squared in square_iter, 3, 0 do print(i, n_squared)end-- 输出:-- 1 1-- 2 4-- 3 9通常,你会将迭代器函数包装在另一个函数(一个工厂函数,factory)中,这个工厂函数为 for 循环设置初始状态,类似于 ipairs 和 pairs 的工作方式。
-- 平方迭代器的工厂函数function squares_factory(limit) -- 返回:迭代器函数,不变状态,初始控制变量值 return square_iter, limit, 0end
print("\n使用工厂函数生成平方:")for i, n_squared in squares_factory(4) do print(i, n_squared)end-- 输出:-- 1 1-- 2 4-- 3 9-- 4 16有状态迭代器
Section titled “有状态迭代器”有状态迭代器使用闭包(closure)在函数调用之间维护其状态。闭包是一个捕获(关闭)其周围局部变量(upvalue)的函数。要创建有状态迭代器,通常会定义一个工厂函数来创建并返回该闭包。
我们来使用闭包创建一个用于数组元素的迭代器。
local fruits = {"Apple", "Banana", "Cherry"}
-- 返回迭代器(一个闭包)的工厂函数function element_iterator_factory(collection) local index = 0 -- 闭包变量(Upvalue),迭代器的状态 local count = #collection -- 闭包变量(Upvalue),另一部分状态
-- 这是闭包,实际的迭代器函数 return function() index = index + 1 if index <= count then return collection[index] -- 返回下一个元素 else return nil -- 没有更多元素了,停止迭代 end endend
print("\n使用有状态迭代器遍历水果:")-- for 循环调用 element_iterator_factory 返回的闭包for fruit in element_iterator_factory(fruits) do print(fruit)end-- 输出:-- Apple-- Banana-- Cherry在这个例子中,element_iterator_factory 被调用一次。它设置了 index 和 count。内部的匿名函数(即闭包)被返回并成为迭代器。每次 for 循环调用这个闭包时,它可以访问并修改其封闭作用域中的 index 闭包变量(upvalue),从而维护其状态。
实际应用: 迭代器在处理集合时无处不在。自定义迭代器对于抽象复杂数据结构或序列(如从文件读取行(io.lines)、遍历树或按需生成值)非常强大。