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

【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.xdnf.cn/news/19319.html

相关文章:

  • String str = new String(“abc“)
  • C语言---零碎语法知识补充(队列、函数指针、左移右移、任务标识符)
  • 第十六章 ESP32S3 WATCH_DOG 实验
  • C++优先级队列priority_queue的模拟实现
  • 论文介绍:《Small Language Models are the Future of Agentic AI》
  • Python(五)Python_C API详细
  • Linux三剑客grep-sed-awk
  • 为什么vue3会移除过滤器filter
  • 北斗导航 | RAIM算法改进方案及性能对比分析报告
  • 深度学习:洞察发展趋势,展望未来蓝图
  • 计算机网络面试集合
  • 【AI工具】在 VSCode中安装使用Excalidraw
  • Java全栈开发面试实战:从基础到微服务的深度解析
  • 小迪安全v2023学习笔记(七十四讲)—— 验证机制篇验证码绕过思路SRC挖掘演示
  • Coze源码分析-API授权-获取令牌列表-前端源码
  • LeetCode刷题记录----51.N皇后(Hard)
  • OpenCV安装及其开发环境配置(Windows系统Visual Studio 2022)
  • ros1ros2区别和相同之处
  • 软考 系统架构设计师系列知识点之杂项集萃(136)
  • 【LeetCode - 每日1题】有效的数独
  • Java基础知识(十)
  • plantsimulation知识点 多条RGV驮一台工件图标显示顺序问题
  • C语言类型转换踩坑解决过程
  • 重叠IO模型
  • 深入理解 Linux 驱动中的 file_operations:从 C 语言函数指针到类比 C++ 虚函数表
  • 学习Python中Selenium模块的基本用法(11:弹窗处理)
  • Day18_【机器学习—交叉验证与网格搜索】
  • 【ROS2】ROS2 基础学习教程 、movelt学习
  • PostgreSQL 数据库灾备要点与举例说明**
  • Spring Data Redis 的使用方法