Lua(迭代器)

Lua 迭代器基础概念

Lua 迭代器是一种允许遍历集合(如数组、表)元素的机制。迭代器通常由两个部分组成:迭代函数和状态控制变量。每次调用迭代函数会返回集合中的下一个元素。

泛型 for 循环

Lua 提供了泛型 for 循环来简化迭代器的使用。语法如下:

lua 复制代码
for var1, var2, ..., varN in iterator_function, state, initial_value do
    -- 循环体
end
  • iterator_function:迭代函数,每次调用返回下一个值。
  • state:迭代器的状态(通常是集合本身)。
  • initial_value:迭代的初始值(通常为 nil)。

无状态迭代器

无状态迭代器不保留任何状态信息,状态完全由外部控制。典型的例子是 ipairspairs

warring:

同:都是能遍历集合(表、数组)

异:ipairs 仅仅遍历值,按照索引升序遍历,索引中断停止遍历。即不能返回 nil,只能返回数字 0,如果遇到 nil 则退出。它只能遍历到集合中出现的第一个不是整数的 key。

pairs 能遍历集合的所有元素。即 pairs 可以遍历集合中所有的 key,并且除了迭代器本身以及遍历表本身还可以返回 nil。

示例:实现类似 ipairs 的迭代器

lua 复制代码
local function iter(t, i)
    i = i + 1
    if t[i] then
        return i, t[i]
    end
end

function my_ipairs(t)
    return iter, t, 0
end

-- 使用
local arr = {10, 20, 30}
for i, v in my_ipairs(arr) do
    print(i, v)
end

有状态迭代器

有状态迭代器将状态封装在闭包或表中,无需外部传递状态。

闭包实现

lua 复制代码
function my_iter(t)
    local i = 0
    return function()
        i = i + 1
        if t[i] then
            return i, t[i]
        end
    end
end

-- 使用
local arr = {10, 20, 30}
for i, v in my_iter(arr) do
    print(i, v)
end

表实现

lua 复制代码
local iterator = {}
iterator.__index = iterator

function iterator.new(t)
    return setmetatable({t = t, i = 0}, iterator)
end

function iterator:__call()
    self.i = self.i + 1
    if self.t[self.i] then
        return self.i, self.t[self.i]
    end
end

-- 使用
local arr = {10, 20, 30}
for i, v in iterator.new(arr) do
    print(i, v)
end

自定义迭代器

通过实现 __pairs__ipairs 元方法,可以自定义表的迭代行为。

示例:逆序遍历数组

lua 复制代码
local function reverse_iter(t, i)
    i = i - 1
    if i > 0 then
        return i, t[i]
    end
end

function reverse_ipairs(t)
    return reverse_iter, t, #t + 1
end

-- 使用
local arr = {10, 20, 30}
for i, v in reverse_ipairs(arr) do
    print(i, v)
end

协程迭代器

协程可以用于实现复杂的迭代逻辑,尤其是需要跨多次调用维护状态的情况。

示例:遍历二叉树

lua 复制代码
local function traverse(node)
    if not node then return end
    traverse(node.left)
    coroutine.yield(node.value)
    traverse(node.right)
end

function 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) do
    print(v) -- 输出 1, 2, 3
end

性能优化建议

  1. 无状态迭代器通常比有状态迭代器更快,因为避免了闭包创建的开销。
  2. 对于大规模数据,优先使用 ipairspairs 而不是自定义迭代器。
  3. 协程迭代器虽然灵活,但会有额外的协程调度开销。
相关推荐
林开落L1 小时前
库的制作与原理
linux·开发语言·动静态库·库的制作
m0_480502642 小时前
Rust 入门 泛型和特征-特征对象 (十四)
开发语言·后端·rust
瓦特what?2 小时前
关于C++的#include的超超超详细讲解
java·开发语言·数据结构·c++·算法·信息可视化·数据挖掘
祁同伟.3 小时前
【C++】动态内存管理
开发语言·c++
一只鲲3 小时前
40 C++ STL模板库9-容器2-vector
开发语言·c++
励志不掉头发的内向程序员3 小时前
C++基础——内存管理
开发语言·c++
lifallen3 小时前
JCTools 无锁并发队列基础:ConcurrentCircularArrayQueue
java·开发语言·数据结构·算法
千里镜宵烛4 小时前
深入理解 Linux 线程:从概念到虚拟地址空间的全面解析
开发语言·c++·操作系统·线程
Eternity_GQM4 小时前
【Word VBA Zotero 引用宏错误分析与改正指南】【解决[21–23]参考文献格式插入超链接问题】
开发语言·c#·word
张柏慈4 小时前
JavaScript性能优化30招
开发语言·javascript·性能优化