Lua 的 pairs 函数

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

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

基本语法:

for key, value in pairs(t) do
    -- 循环体
end

工作原理

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

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

与 ipairs 的区别

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

实际应用示例

1. 遍历混合类型表

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可以自定义遍历行为:

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. 按排序后的键顺序访问值
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
### Lua 脚本中的常用函数列表及其用法 Lua 是一种轻量级的嵌入式脚本语言,在许多场景下被广泛使用,比如游戏开发、Web 开发以及作为 Redis 中的安全沙盒环境。以下是 Lua 脚本中常用的内置函数及其示例。 #### 1. `print` 函数 用于打印输出到控制台。 ```lua print("Hello, world!") -- 输出 Hello, world! ``` #### 2. 数学库函数 Lua 提供了一个丰富的数学库来处理各种数值计算。 - **`math.abs(x)`**: 返回绝对值。 - **`math.ceil(x)`**: 向上取整。 - **`math.floor(x)`**: 向下取整。 - **`math.max(...)`**: 返回最大值。 - **`math.min(...)`**: 返回最小值。 示例: ```lua local absValue = math.abs(-5) -- 结果为 5 local ceilValue = math.ceil(3.2) -- 结果为 4 local floorValue = math.floor(3.8) -- 结果为 3 local maxValue = math.max(1, 3, 5, 7) -- 结果为 7 local minValue = math.min(1, 3, 5, 7) -- 结果为 1 ``` #### 3. 字符串操作函数 字符串是 Lua 中的重要数据类型之一,提供了多种方法来进行字符串处理。 - **`string.len(s)`**: 计算字符串长度。 - **`string.sub(s, i, j)`**: 截取子字符串。 - **`string.upper(s)`**: 将字符串转换为大写。 - **`string.lower(s)`**: 将字符串转换为小写。 示例: ```lua local strLength = string.len("hello") -- 结果为 5 local subStr = string.sub("hello", 2, 4) -- 结果为 "ell" local upperCase = string.upper("hello") -- 结果为 "HELLO" local lowerCase = string.lower("WORLD") -- 结果为 "world" ``` #### 4. 表(Table)操作函数 表是 Lua 中唯一的复合数据结构,类似于数组和哈希表的组合。 - **`table.insert(t, value)`**: 插入元素到表末尾。 - **`table.remove(t, index)`**: 移除指定索引处的元素。 - **`pairs(t)`**: 遍历表的所有键值对。 示例: ```lua local t = {} table.insert(t, "a") -- 添加 "a" 到表末尾 table.insert(t, "b") -- 添加 "b" 到表末尾 for key, value in pairs(t) do print(key, value) end -- 输出: -- 1 a -- 2 b ``` #### 5. 文件操作函数 虽然文件操作通常由宿主程序提供支持,但在某些情况下可以直接调用 Lua 的标准 I/O 库。 - **`io.open(filename, mode)`**: 打开文件。 - **`file:read([format])`**: 读取文件内容。 - **`file:write(text)`**: 写入文件内容。 示例: ```lua local file = io.open("example.txt", "w") if file then file:write("Hello, Lua!") file:close() end ``` #### 6. Redis 特定函数 (Redis 环境下的 Lua 使用)[^3] 在 Redis 中运行的 Lua 脚本可以访问特定于 Redis 的 API 来执行命令。 - **`redis.call(command, ...)`**: 发送命令给 Redis 并返回结果。 - **`tonumber(value)`**: 将字符串或其他类型的值转换为数字。 示例: ```lua local stock = redis.call('GET', KEYS[1]) if tonumber(stock) <= 0 then return '库存不足' else redis.call('DECR', KEYS[1]) return '成功扣减库存' end ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值