Lua 的 pairs 函数

Lua 的 pairs 函数 是 Lua 中用于遍历表(table)的迭代器函数,它会返回三个值:

  1. 迭代器函数
  2. 表本身
  3. 初始索引(nil)

基本语法:

lua 复制代码
for key, value in pairs(t) do
    -- 循环体
end

工作原理

pairs 会遍历表中的所有键值对,包括:

  • 数组部分(连续数字索引)
  • 哈希部分(非数字索引或非连续数字索引)
  • 元表中的__pairs元方法(如果存在)

与 ipairs 的区别

特性 pairs ipairs
遍历范围 所有键值对 仅连续数字索引(1,2,3...)
顺序 不确定 从1开始顺序遍历
跳过nil 不跳过 遇到nil则停止
元表支持 支持__pairs 不支持元方法

实际应用示例

1. 遍历混合类型表

lua 复制代码
local t = {
    "apple",          -- 索引1
    "banana",         -- 索引2
    color = "red",    -- 字符串键
    [5] = "orange",   -- 非连续数字索引
    [true] = "yes"    -- 布尔值键
}

for k, v in pairs(t) do
    print(k, v)
end
-- 可能的输出(顺序不确定):
-- 1       apple
-- 2       banana
-- 5       orange
-- color   red
-- true    yes

2. 实现自定义迭代器

通过元表__pairs可以自定义遍历行为:

lua 复制代码
local mt = {
    __pairs = function(t)
        local keys = {}
        for k in pairs(t) do
            if type(k) == "string" then  -- 只遍历字符串键
                table.insert(keys, k)
            end
        end
        table.sort(keys)  -- 按字母顺序排序
        local i = 0
        return function()
            i = i + 1
            if keys[i] then
                return keys[i], t[keys[i]]
            end
        end
    end
}

local t = setmetatable({a=1, b=2, [1]="x", [2]="y"}, mt)

for k, v in pairs(t) do
    print(k, v)  -- 只会输出 a 1 和 b 2,且按字母顺序
end

性能注意事项

  1. pairs 的遍历顺序是不确定的,不要依赖特定的键顺序
  2. 对于纯数组表(连续数字索引),ipairs 通常比 pairs 更高效
  3. 在遍历过程中修改表(增删键)可能导致不可预期的行为

常见问题

为什么有时 pairs 会跳过某些元素?

这通常是因为:

  • 键包含特殊值(如 NaN)
  • 表在遍历过程中被修改
  • 使用了弱引用表

如何保证遍历顺序?

如果需要特定顺序,可以:

  1. 先收集所有键到数组
  2. 对数组排序
  3. 按排序后的键顺序访问值
lua 复制代码
local t = {z=3, a=1, b=2}
local keys = {}

for k in pairs(t) do
    table.insert(keys, k)
end

table.sort(keys)

for _, k in ipairs(keys) do
    print(k, t[k])  -- 输出 a 1, b 2, z 3
end
相关推荐
IT_陈寒16 分钟前
Redis内存爆了,原来我漏掉了这个致命配置
前端·人工智能·后端
fliter1 小时前
最后一块拼图:用 bitvec 构造 IPv4 包,真正做出自己的 Ping
后端
fliter2 小时前
用 Rust 解析并生成 ICMP 包:checksum、nom 与 cookie-factory
后端
蝎子莱莱爱打怪2 小时前
XZLL-IM干货系列 03|消息 ID 设计:一个 UUID 搞不定的事,我用两个 ID 解决了
后端·面试·开源
fliter2 小时前
从 panic 到 Result:用 Rust 重新整理一个 ping 项目的错误处理
后端
森蓝情丶3 小时前
我给 AI 搭了个法庭:一个前端仔的 LangGraph 实战全记录
前端·后端
JensCS猿3 小时前
从 Spring Boot 回看 SSM 框架:手动挡与自动挡的驾驶哲学
后端
爱勇宝3 小时前
干了近 8 年,一夜之间被裁:AI 时代,程序员最该害怕的不是 AI
前端·后端·程序员
科米米3 小时前
嵌入式日志模块
后端
血小溅3 小时前
三大 AI 编码框架深度对比:GSD vs OpenSpec vs Superpowers
人工智能·后端