当前位置: 首页 > news >正文

【lua】table基础操作

🛫 导读

在这里插入图片描述

需求

本教程面向 Lua 初学者及需要深化 table 应用的开发者,核心解决以下需求:

  • 理解 table 作为 Lua 唯一数据结构的本质特性,
  • 掌握 table 的创建、增删改查等基础操作,
  • 攻克遍历、排序、嵌套等进阶场景,最终能灵活运用 table 实现数组、字典、结构化数据存储(如游戏角色属性、用户信息表)等实际开发需求,规避使用中的常见问题(如索引混乱、长度计算误差)。

开发环境

版本号描述
文章日期2025-08-30
IDEhttps://www.mycompiler.io/new/lua5.3

1️⃣ table核心认知:Lua的“万能数据容器”

table是Lua语言的基石数据结构,无固定类型限制可同时存储数值、字符串、函数甚至其他table,本质是“键值对(key-value)集合”。
其独特性在于:既支持“数值键”(模拟数组,索引从1开始),也支持“自定义键”(模拟字典),且两种模式可混合使用,满足多样化数据组织需求。

table的两种核心模式

  1. 数组模式:键为连续整数(默认从1开始),适合存储有序列表(如商品列表、分数排名),示例:
    -- 数组模式:存储3个学生姓名,键自动为1、2、3
    studentNames = {"张三", "李四", "王五"}
    print(studentNames[1])  -- 输出:张三(注意:非0开始)
    print(studentNames[3])  -- 输出:王五
    
  2. 字典模式:键为自定义字符串/数值(非连续),适合存储关联数据(如用户属性、配置信息),示例:
    -- 字典模式:存储用户信息,键为自定义字符串
    userInfo = {name = "赵六", age = 25, isVip = true}
    print(userInfo.age)  -- 输出:25(语法糖写法)
    print(userInfo["isVip"]) -- 输出:true(标准写法)
    

table的创建方式

Lua提供两种创建table的方式,根据数据确定性选择:

  1. 空table初始化:先创建空容器,后续动态添加数据,适合数据未知场景:
-- 步骤1:创建空table
shoppingCart = {}
-- 步骤2:动态添加数据(数组模式+字典模式)
shoppingCart[1] = "牛奶"    -- 数组模式:键1
shoppingCart[2] = "面包"    -- 数组模式:键2
shoppingCart.count = 2      -- 字典模式:键count
print(#shoppingCart)           -- 输出2,只计算从1开始的连续数组长度
  1. 直接赋值初始化:创建时直接定义所有键值对,适合数据已知场景,示例:
-- 直接初始化:混合存储书籍信息
book = {"Lua程序设计", "Python入门",  -- 数组:键1-2(书籍名称)author = "Lua团队",          -- 字典:键author(作者)price = 59.9                 -- 字典:键price(价格)
}
print(#shoppingCart)          -- 输出2,只计算从1开始的连续数组

2️⃣ table基础操作:增删改查与长度计算

掌握“增、删、改、查”是table使用的核心,而长度计算是衡量table规模的基础操作,需理解#运算符的适用范围与限制。

新增数据(增)

  1. 数组模式新增

    • 直接赋值:通过“最大索引+1”添加,适合有序扩展:

      fruits = {"苹果", "香蕉"}
      fruits[3] = "橙子"  -- 最大索引为2,新增索引3
      print(fruits[3])    -- 输出:橙子
      
    • 内置函数table.insert(t, pos, value):指定位置插入(pos可选,默认末尾),示例:

      table.insert(fruits, "葡萄")  -- 末尾插入,数组变为{"苹果","香蕉","橙子","葡萄"}
      table.insert(fruits, 2, "草莓")-- 索引2插入,数组变为{"苹果","草莓","香蕉","橙子","葡萄"}
      
  2. 字典模式新增:直接通过“键=值”赋值,不存在的键会自动创建:

function printT(t)for i, v in pairs(t) doprint(i, v)end
endphone = {brand = "华为", model = "Mate 60"}
phone.color = "黑色"    -- 新增键color
phone["storage"] = "512G"  -- 新增键storage
-- print(phone.color, phone.storage)  -- 输出:黑色 512G
printT(phone)

删除数据(删)

  1. 数组模式删除:使用table.remove(t, pos)(pos可选,默认末尾),删除后后续元素自动前移:

    function printT(t)print('====================')for i, v in pairs(t) doprint(i, v)end
    endfruits = {"苹果","草莓","香蕉","橙子","葡萄"}
    table.remove(fruits, 2)  -- 删除索引2的"草莓",数组变为{"苹果","香蕉","橙子","葡萄"}
    printT(fruits)
    table.remove(fruits)     -- 删除末尾的"葡萄",数组变为{"苹果","香蕉","橙子"}
    printT(fruits)
    
  2. 字典模式删除:将键的值设为nil(Lua中nil表示“无值”,等同于删除键值对):

    function printT(t)print('====================')for i, v in pairs(t) doprint(i, v)end
    endphone = {brand = "华为", model = "Mate 60", color = "黑色"}
    phone.color = nil  -- 删除键color
    print(phone.color) -- 输出:nil(表示键已不存在)
    printT(phone)
    

修改与查询(改、查)

  1. 修改数据:对已有键重新赋值,覆盖原有值:

    student = {name = "张三", score = 80}
    student.score = 85  -- 修改score的值为85
    student["name"] = "张三丰"  -- 修改name的值为"张三丰"
    print(student.name, student.score)  -- 输出:张三丰 85
    
  2. 查询数据:通过“键”获取值,若键不存在则返回nil

    book = {title = "Lua入门", price = 49.9}
    print(book.title)      -- 输出:Lua入门(字典模式查询)
    nums = {10, 20, 30}
    print(nums[2])         -- 输出:20(数组模式查询)
    print(book.author)     -- 输出:nil(键author不存在)
    

table长度计算(#运算符)

Lua通过#运算符获取table长度,但仅对数组模式(连续整数键) 有效,返回最大连续整数键值,对字典模式或非连续数组不适用:

  1. 连续数组#返回预期长度:
    arr = {"a", "b", "c"}
    print(#arr)  -- 输出:3(最大连续键为3)
    
  2. 非连续数组#返回第一个nil前的最大键(结果可能不符合预期):
    arr = {"a", "b"}
    arr[4] = "d"  -- 键3为nil(不连续)
    print(#arr)   -- 输出:2(因键3为nil,中断连续)
    
  3. 混合模式#仅计算数组部分,忽略字典部分:
    mix = {"a", "b", count = 2}  -- 数组键1-2,字典键count
    print(#mix)  -- 输出:2(仅统计数组部分)
    
  4. 计算全量长度(含字典):需手动遍历计数:
    function getTotalLength(t)local count = 0for _ in pairs(t) do  -- pairs遍历所有键count = count + 1endreturn count
    end
    mix = {"a", "b", count = 2}
    print(getTotalLength(mix))  -- 输出:3(数组2个+字典1个)
    

3️⃣ table遍历:ipairspairsnext函数

遍历是获取table全部数据的核心操作,ipairspairsnext函数各有适用场景,需根据table类型选择。

ipairs:连续整数键的专属遍历

ipairs(t)仅遍历从1开始的连续整数键,遇到非整数键或中断的整数键(如键1存在,键2不存在)则停止,适合纯数组:

arr = {"a", "b"}
arr[4] = "d"  -- 键3缺失(中断)
arr["key"] = "c"  -- 非整数键for i, v in ipairs(arr) doprint(i, v)
end
-- 输出:
-- 1   a
-- 2   b
-- (键3缺失,键4和"key"被忽略)

pairs:连续整数键的专属遍历

遍历所有键值对(无论键类型/是否连续),适合混合模式/纯字典模式:

-- pairs遍历:输出所有键值对(键顺序不固定,按Lua哈希表规则)
for key, value in pairs(mixTable) doprint("键:" .. tostring(key) .. ",值:" .. tostring(value))
end
-- 输出(顺序可能不同):
-- 键:1,值:a
-- 键:2,值:b
-- 键:4,值:d
-- 键:key,值:c

next:底层键值对遍历工具

next(t, key)是Lua底层遍历函数,返回table中“指定key的下一个键值对”,参数keynil时返回第一个键值对,无下一个时返回nil。可替代pairs实现灵活遍历:

  1. 基本用法(模拟pairs
    t = {a = 1, b = 2, c = 3}
    local key, value = next(t, nil)  -- 从第一个键开始
    while key doprint(key, value)key, value = next(t, key)  -- 获取下一个键值对
    end
    -- 输出(顺序不固定):
    -- a   1
    -- b   2
    -- c   3
    
  2. ipairs的差异next可遍历所有键(包括非整数、不连续键),ipairs仅遍历连续整数键:
    mix = {10, 20, [4] = 40, name = "test"}
    -- next遍历所有键
    key, value = next(mix, nil)
    while key doprint(key, value)key, value = next(mix, key)
    end
    -- 输出(含键1、2、4、name)
    

3️⃣ table排序、嵌套

数组排序:table.sort的使用

table.sort(t, compare)用于对数组模式的table排序,compare为可选比较函数(默认升序):

  1. 默认升序排序:适用于数值/字符串数组(字符串按ASCII码排序):
    -- 数值数组升序
    nums = {5, 2, 8, 1}
    table.sort(nums)
    print(table.concat(nums, ", "))  -- 输出:1, 2, 5, 8(concat用于拼接数组)-- 字符串数组升序(按ASCII码)
    words = {"banana", "apple", "cherry"}
    table.sort(words)
    print(table.concat(words, ", "))  -- 输出:apple, banana, cherry
    
  2. 自定义排序:通过比较函数实现降序或复杂排序(如按table嵌套字段排序):
    -- 数值数组降序
    nums = {5, 2, 8, 1}
    table.sort(nums, function(a, b)return a > b  -- a > b时交换,实现降序
    end)
    print(table.concat(nums, ", "))  -- 输出:8, 5, 2, 1-- 嵌套table排序:按学生分数降序
    students = {{name = "张三", score = 85},{name = "李四", score = 92},{name = "王五", score = 78}
    }
    table.sort(students, function(a, b)return a.score > b.score  -- 按score字段降序
    end)
    -- 遍历排序结果
    for i, stu in ipairs(students) doprint(i .. ". " .. stu.name .. ":" .. stu.score)
    end
    -- 输出:
    -- 1. 李四:92
    -- 2. 张三:85
    -- 3. 王五:78
    

嵌套table:实现复杂数据结构

嵌套table即“table内存储其他table”,可实现二维数组、树形结构等复杂场景,示例:

  1. 二维数组(矩阵):存储表格类数据(如成绩表):
    -- 二维数组:3行2列(行=学生,列=科目分数)
    scoreTable = {{math = 90, english = 85},  -- 学生1的分数{math = 88, english = 92},  -- 学生2的分数{math = 76, english = 80}   -- 学生3的分数
    }
    -- 获取学生2的英语分数
    print(scoreTable[2].english)  -- 输出:92
    
  2. 结构化数据:存储多层关联信息(如游戏角色属性):
    -- 嵌套table:游戏角色属性
    role = {name = "战士",level = 50,skills = {  -- 技能列表(嵌套table){name = "猛击", damage = 120},{name = "防御", defense = 80}},equipment = {  -- 装备信息(嵌套table)weapon = "铁剑",armor = "钢甲"}
    }
    -- 获取角色第一个技能的伤害
    print(role.skills[1].damage)  -- 输出:120
    

🛬 文章小结

  1. 长度计算#运算符仅适用于连续整数键数组,返回最大连续索引;含字典或非连续键的table需手动遍历计数;
  2. 遍历工具ipairs专注连续整数键(从1开始,中断则停),next可遍历所有键(底层函数,支持灵活控制遍历过程);
  3. 最佳实践:纯数组用ipairs+#,混合/字典模式用next(或pairs)+手动计数,避免依赖#处理非连续结构。

📖 参考资料

  • Lua官方手册:Lua 5.3 Reference Manual
http://www.dtcms.com/a/358123.html

相关文章:

  • 欧司朗对Spider Farmer提起专利诉讼
  • Vue常用指令和生命周期
  • TimeDP Learning to Generate Multi-Domain Time Series with Domain Prompts论文阅读笔记
  • Kubernetes 部署与发布完全指南:从 Pod 到高级发布策略
  • 一款支持动态定义路径的JAVA内存马维权工具Agenst
  • ifconfig 和 ip addr show 输出详细解读
  • `basic_filebuf`、`basic_ifstream`、`basic_ofstream`和 `basic_fstream`。
  • 【高级机器学习】 4. 假设复杂度与泛化理论详解
  • 【超全汇总】MySQL服务启动命令手册(Linux+Windows+macOS)(上)
  • React前端开发_Day10
  • 针对 “TCP 连接建立阶段” 的攻击
  • PAT 1088 Rational Arithmetic
  • android adb调试 鸿蒙
  • 微信小程序长按识别图片二维码
  • mysql的内置函数
  • psql介绍(PostgreSQL命令行工具)(pgAdmin内置、DBeaver、Azure Data Studio)数据库命令行工具
  • 三数之和,leetCode热题100,C++实现
  • Ubuntu 中通过 SSH 克隆 Windows 上的 Git 仓库
  • C++转置正方形矩阵
  • components.d.ts声明组件类型的作用
  • LeetCode100-240搜索二维矩阵Ⅱ
  • linux基础——UDP、TCP
  • 北斗导航 | RAIM算法改进方案及性能对比分析报告
  • 力扣(LeetCode) ——645. 错误的集合(C语言)
  • 算法(③二叉树)
  • 精简版UDP网络编程:Socket套接字应用
  • 网格纹理采样算法
  • U盘/移动硬盘里可清理的那些跨系统遗留文件
  • 使用JAVA制作minecraft红石和创造模式插件
  • 理解JVM