表基础 #
一、表概述 #
1.1 什么是表 #
表(Table)是 Lua 中唯一的数据结构,它可以用来表示:
- 数组
- 字典/映射
- 对象
- 模块
- 命名空间
lua
-- 表是 Lua 的核心数据结构
local t = {} -- 创建空表
1.2 表的特点 #
- 动态:可以随时添加和删除字段
- 灵活:键可以是除 nil 外的任何类型
- 引用类型:变量存储的是表的引用
二、创建表 #
2.1 空表 #
lua
-- 创建空表
local t1 = {}
local t2 = table.new and table.new(0, 0) or {} -- 预分配(Lua 5.3+)
2.2 数组风格 #
lua
-- 数组风格创建
local arr1 = {1, 2, 3, 4, 5}
local arr2 = {"a", "b", "c"}
-- 索引从 1 开始
print(arr1[1]) -- 1
print(arr1[5]) -- 5
2.3 字典风格 #
lua
-- 字典风格创建
local person = {
name = "张三",
age = 25,
city = "北京"
}
print(person.name) -- 张三
print(person["age"]) -- 25
2.4 混合风格 #
lua
-- 混合风格
local mixed = {
1, 2, 3, -- 数组部分
name = "Lua", -- 字典部分
[10] = "第十个", -- 指定索引
["key with space"] = "值" -- 字符串键
}
print(mixed[1]) -- 1
print(mixed.name) -- Lua
print(mixed[10]) -- 第十个
2.5 嵌套表 #
lua
-- 嵌套表
local company = {
name = "TechCorp",
address = {
city = "北京",
street = "中关村大街"
},
employees = {
{name = "张三", age = 30},
{name = "李四", age = 28}
}
}
print(company.address.city) -- 北京
print(company.employees[1].name) -- 张三
三、访问表 #
3.1 点语法 #
lua
local person = {name = "张三", age = 25}
-- 点语法访问
print(person.name) -- 张三
-- 点语法赋值
person.city = "北京"
print(person.city) -- 北京
3.2 方括号语法 #
lua
local person = {name = "张三", age = 25}
-- 方括号访问
print(person["name"]) -- 张三
-- 方括号赋值
person["city"] = "北京"
-- 动态键名
local key = "name"
print(person[key]) -- 张三
3.3 两种语法的区别 #
lua
local t = {}
-- 点语法:键必须是有效的标识符
t.name = "Lua" -- 正确
-- t.123 = "数字" -- 错误
-- t.my-key = "连字符" -- 错误
-- 方括号语法:键可以是任意类型
t[123] = "数字键" -- 正确
t["my-key"] = "连字符" -- 正确
t[function() end] = "函数键" -- 正确(但不推荐)
-- 访问时也需要使用方括号
print(t[123]) -- 数字键
print(t["my-key"]) -- 连字符
四、表的遍历 #
4.1 ipairs 遍历数组 #
lua
local arr = {"a", "b", "c", "d", "e"}
-- ipairs:遍历数组部分(从 1 开始连续整数索引)
for i, v in ipairs(arr) do
print(i, v)
end
-- 1 a
-- 2 b
-- 3 c
-- 4 d
-- 5 e
-- 注意:ipairs 遇到 nil 会停止
local sparse = {1, 2, nil, 4}
for i, v in ipairs(sparse) do
print(i, v)
end
-- 只输出:1 1 和 2 2
4.2 pairs 遍历所有 #
lua
local t = {
a = 1,
b = 2,
c = 3,
[1] = "first",
[2] = "second"
}
-- pairs:遍历所有键值对
for k, v in pairs(t) do
print(k, v)
end
-- 输出顺序不确定
4.3 数值 for 遍历 #
lua
local arr = {10, 20, 30, 40, 50}
-- 数值 for:适合已知长度
for i = 1, #arr do
print(i, arr[i])
end
-- 逆序遍历
for i = #arr, 1, -1 do
print(i, arr[i])
end
4.4 遍历嵌套表 #
lua
local matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}
-- 遍历二维数组
for i = 1, #matrix do
for j = 1, #matrix[i] do
io.write(matrix[i][j] .. " ")
end
io.write("\n")
end
五、表的长度 #
5.1 # 操作符 #
lua
-- 获取数组长度
local arr = {1, 2, 3, 4, 5}
print(#arr) -- 5
-- 空表
print(#{}) -- 0
-- 字典长度
local dict = {a = 1, b = 2, c = 3}
print(#dict) -- 0(# 不适用于字典)
5.2 长度的陷阱 #
lua
-- 稀疏数组
local sparse = {1, 2, nil, 4, 5}
print(#sparse) -- 不确定,可能是 5 或 2
-- 正确计算元素数量
local function count_elements(t)
local count = 0
for _ in pairs(t) do
count = count + 1
end
return count
end
print(count_elements({a = 1, b = 2, c = 3})) -- 3
六、表的复制 #
6.1 浅拷贝 #
lua
-- 浅拷贝
local function shallow_copy(t)
local copy = {}
for k, v in pairs(t) do
copy[k] = v
end
return copy
end
local original = {a = 1, b = {c = 2}}
local copy = shallow_copy(original)
copy.a = 10
print(original.a) -- 1(不受影响)
copy.b.c = 20
print(original.b.c) -- 20(受影响,因为嵌套表是引用)
6.2 深拷贝 #
lua
-- 深拷贝
local function deep_copy(t, visited)
visited = visited or {}
if type(t) ~= "table" then
return t
end
if visited[t] then
return visited[t]
end
local copy = {}
visited[t] = copy
for k, v in pairs(t) do
copy[deep_copy(k, visited)] = deep_copy(v, visited)
end
return copy
end
local original = {a = 1, b = {c = 2}}
local copy = deep_copy(original)
copy.b.c = 20
print(original.b.c) -- 2(不受影响)
七、表的操作 #
7.1 添加元素 #
lua
local t = {}
-- 直接赋值
t.name = "Lua"
-- 表尾添加(数组)
table.insert(t, "a")
table.insert(t, "b")
-- 指定位置插入
table.insert(t, 1, "first")
7.2 删除元素 #
lua
local t = {a = 1, b = 2, c = 3}
-- 设置为 nil
t.b = nil
-- 删除数组元素
local arr = {1, 2, 3, 4, 5}
local removed = table.remove(arr, 2) -- 删除第 2 个
print(removed) -- 2
print(arr[2]) -- 3
7.3 修改元素 #
lua
local t = {a = 1, b = 2}
-- 直接修改
t.a = 10
-- 批量修改
local function update(t, updates)
for k, v in pairs(updates) do
t[k] = v
end
end
update(t, {a = 100, c = 300})
print(t.a, t.c) -- 100 300
八、表的合并 #
8.1 合并两个表 #
lua
local function merge(t1, t2)
local result = {}
for k, v in pairs(t1) do
result[k] = v
end
for k, v in pairs(t2) do
result[k] = v
end
return result
end
local a = {x = 1, y = 2}
local b = {y = 20, z = 3}
local c = merge(a, b)
print(c.x, c.y, c.z) -- 1 20 3
8.2 合并数组 #
lua
local function concat_arrays(...)
local result = {}
for i = 1, select("#", ...) do
local arr = select(i, ...)
for _, v in ipairs(arr) do
table.insert(result, v)
end
end
return result
end
local merged = concat_arrays({1, 2}, {3, 4}, {5, 6})
print(table.concat(merged, ", ")) -- 1, 2, 3, 4, 5, 6
九、表的序列化 #
9.1 转换为字符串 #
lua
local function serialize(t, indent)
indent = indent or ""
local result = {}
table.insert(result, "{")
for k, v in pairs(t) do
local key
if type(k) == "string" and k:match("^[%a_][%w_]*$") then
key = k
else
key = "[" .. serialize(k) .. "]"
end
local value
if type(v) == "table" then
value = serialize(v, indent .. " ")
elseif type(v) == "string" then
value = string.format("%q", v)
else
value = tostring(v)
end
table.insert(result, indent .. " " .. key .. " = " .. value .. ",")
end
table.insert(result, indent .. "}")
return table.concat(result, "\n")
end
local t = {name = "Lua", version = 5.4, features = {"fast", "light"}}
print(serialize(t))
十、总结 #
本章介绍了 Lua 表的基础知识:
- 表概述:Lua 唯一的数据结构
- 创建表:空表、数组、字典、混合、嵌套
- 访问表:点语法和方括号语法
- 遍历表:ipairs、pairs、数值 for
- 表长度:# 操作符及其陷阱
- 表复制:浅拷贝和深拷贝
- 表操作:添加、删除、修改、合并
表是 Lua 的核心,下一章我们将学习表作为数组的高级用法。
最后更新:2026-03-27