Lua 表操作教程

本教程基于 tables.lua 文件,详细介绍 Lua 编程语言中的表(Table)相关知识。表是 Lua 中唯一的数据结构,非常灵活强大,可以用来表示数组、字典等各种数据结构。

目录

  1. 表的基本概念
  2. 数组(数值索引表)
  3. 字典(字符串索引表)
  4. 混合表
  5. 表遍历
  6. 表操作函数
  7. 嵌套表
  8. 表的拷贝
  9. 表的元表
  10. 额外内容:表的长度计算和特殊用法

1. 表的基本概念

表是 Lua 中唯一的数据结构,可以用来表示各种复杂的数据。表是一种关联数组,能够将不同类型的值(包括其他表)与键关联起来。

1
2
3
4
-- 空表
local empty_table = {}
print("Empty table:", empty_table)
print("Type of empty_table:", type(empty_table))

额外示例:表的创建方式

1
2
3
4
5
6
7
8
9
10
-- 直接创建表
local t1 = {} -- 空表
local t2 = {1, 2, 3} -- 数组形式
local t3 = {x = 10, y = 20} -- 字典形式

-- 使用构造函数创建表
local t4 = table.new(0, 2) -- 创建一个预分配空间的表(需要 LuaJIT)
print("Table t1:", t1)
print("Table t2:", t2)
print("Table t3:", t3)

2. 数组(数值索引表)

数组是一种使用数值作为索引的表。在 Lua 中,数组的索引从 1 开始,这与许多其他编程语言不同。

1
2
3
4
5
6
7
8
9
10
-- 整数索引表,索引从1开始
local fruits = {"apple", "banana", "orange", "grape"}
print("Fruits table:")
print("First fruit:", fruits[1]) -- Lua数组索引从1开始
print("Second fruit:", fruits[2])
print("Number of fruits:", #fruits) -- #操作符获取表长度

-- 手动指定索引
local numbers = {[1] = 10, [2] = 20, [3] = 30}
print("Numbers table:", numbers[1], numbers[2], numbers[3])

额外示例:稀疏数组

1
2
3
4
5
6
7
8
9
10
-- 稀疏数组:不是所有索引都有值的数组
local sparse_array = {}
sparse_array[1] = "first"
sparse_array[100] = "hundredth"
sparse_array[1000] = "thousandth"

print("Sparse array[1]:", sparse_array[1])
print("Sparse array[100]:", sparse_array[100])
print("Sparse array[1000]:", sparse_array[1000])
print("Length of sparse array:", #sparse_array) -- 只计算连续部分

3. 字典(字符串索引表)

字典是一种使用字符串作为键的表,也称为关联数组。在 Lua 中,可以使用点表示法或方括号表示法访问字典中的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
local person = {
name = "John",
age = 30,
city = "New York",
is_student = false
}

print("Person table:")
print("Name:", person.name) -- 点表示法
print("Age:", person["age"]) -- 方括号表示法

-- 添加新键值对
person.occupation = "Engineer"
person["salary"] = 50000
print("Occupation:", person.occupation)
print("Salary:", person.salary)

-- 删除键值对
person.is_student = nil
print("After deleting is_student:", person.is_student)

额外示例:使用动态键

1
2
3
4
5
6
7
8
9
-- 使用动态键
local key = "language"
local settings = {}
settings[key] = "Lua"
settings["version"] = "5.1"

print("Settings[language]:", settings[language]) -- 错误:language 未定义
print("Settings[key]:", settings[key]) -- 正确:使用变量作为键
print("Settings['language']:", settings["language"]) -- 正确:使用字符串字面量作为键

4. 混合表

混合表是同时包含数组部分(数值索引)和字典部分(字符串索引)的表。在 Lua 中,这两种部分可以共存于同一个表中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
local mixed_table = {
"first", -- 索引1
"second", -- 索引2
name = "mixed",
value = 100,
"third" -- 索引3
}

print("Mixed table:")
print("Index 1:", mixed_table[1])
print("Index 2:", mixed_table[2])
print("Index 3:", mixed_table[3])
print("Name:", mixed_table.name)
print("Value:", mixed_table.value)
print("Length of mixed_table:", #mixed_table) -- 只计算数组部分

额外示例:混合表的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 混合表的应用:表示一个游戏角色
local player = {
"warrior", -- 职业
"level 10", -- 等级
name = "Hero",
hp = 100,
mp = 50,
inventory = {"sword", "shield", "potion"}
}

print("Player class:", player[1])
print("Player level:", player[2])
print("Player name:", player.name)
print("Player HP:", player.hp)
print("Player inventory:", table.concat(player.inventory, ", "))

5. 表遍历

Lua 提供了两种主要的表遍历方式:ipairspairs

使用 ipairs 遍历数组部分

ipairs 函数用于遍历表的数组部分,只遍历连续的数值索引,按顺序从 1 开始。

1
2
3
4
5
-- 使用ipairs遍历数组部分(仅遍历数值索引,按顺序)
print("Using ipairs to iterate fruits:")
for index, fruit in ipairs(fruits) do
print("Index", index, ":", fruit)
end

使用 pairs 遍历整个表

pairs 函数用于遍历整个表,包括数组部分和字典部分,遍历顺序是不确定的。

1
2
3
4
5
6
7
8
9
10
11
-- 使用pairs遍历整个表(包括数组和字典部分,无序)
print("\nUsing pairs to iterate person:")
for key, value in pairs(person) do
print(key, ":", value)
end

-- 遍历混合表
print("\nUsing pairs to iterate mixed_table:")
for key, value in pairs(mixed_table) do
print(key, ":", value)
end

额外示例:遍历技巧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- 按顺序遍历字典键
local sorted_person = {}
for key in pairs(person) do
table.insert(sorted_person, key)
end
table.sort(sorted_person)

print("Sorted keys in person:")
for _, key in ipairs(sorted_person) do
print(key, ":", person[key])
end

-- 遍历指定范围的数组
local numbers = {10, 20, 30, 40, 50, 60, 70}
print("Numbers from index 2 to 5:")
for i = 2, 5 do
print("Index", i, ":", numbers[i])
end

6. 表操作函数

Lua 提供了一组内置的表操作函数,位于 table 模块中。

table.insert:插入元素

1
2
3
4
5
6
7
8
9
-- table.insert:在指定位置插入元素
local numbers = {1, 2, 3, 4, 5}
print("Original numbers:", table.concat(numbers, ", "))

table.insert(numbers, 3, 100) -- 在索引3处插入100
print("After table.insert(numbers, 3, 100):", table.concat(numbers, ", "))

table.insert(numbers, 200) -- 在末尾插入200
print("After table.insert(numbers, 200):", table.concat(numbers, ", "))

table.remove:删除元素

1
2
3
4
5
6
7
8
-- table.remove:删除指定位置的元素
local removed = table.remove(numbers, 3) -- 删除索引3处的元素
print("Removed element:", removed)
print("After table.remove(numbers, 3):", table.concat(numbers, ", "))

removed = table.remove(numbers) -- 删除末尾元素
print("Removed element:", removed)
print("After table.remove(numbers):", table.concat(numbers, ", "))

table.sort:排序

1
2
3
4
5
6
7
8
9
10
11
12
-- table.sort:排序
local unsorted = {5, 2, 8, 1, 9, 3}
print("\nUnsorted:", table.concat(unsorted, ", "))

table.sort(unsorted)
print("Sorted ascending:", table.concat(unsorted, ", "))

-- 降序排序
table.sort(unsorted, function(a, b)
return a > b
end)
print("Sorted descending:", table.concat(unsorted, ", "))

table.concat:连接元素

1
2
3
4
5
6
7
-- table.concat:连接表元素为字符串
local words = {"Hello", "World", "Lua"}
local sentence = table.concat(words, " ")
print("\nConcatenated string:", sentence)

local numbers_str = table.concat({1, 2, 3, 4, 5}, "-")
print("Concatenated numbers:", numbers_str)

table.unpack:解包元素

1
2
3
4
-- table.unpack:将表元素作为可变参数返回
local coords = {10, 20, 30}
local x, y, z = unpack(coords) -- Lua 5.1 使用 unpack,Lua 5.2+ 使用 table.unpack
print("\nUnpacked coordinates:", x, y, z)

额外示例:其他表操作函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- 查找元素索引
function find_index(tbl, value)
for i, v in ipairs(tbl) do
if v == value then
return i
end
end
return nil
end

local fruits = {"apple", "banana", "orange", "grape"}
print("Index of 'banana':", find_index(fruits, "banana"))
print("Index of 'pear':", find_index(fruits, "pear"))

-- 反转表
function reverse_table(tbl)
local reversed = {}
for i = #tbl, 1, -1 do
table.insert(reversed, tbl[i])
end
return reversed
end

local reversed_fruits = reverse_table(fruits)
print("Reversed fruits:", table.concat(reversed_fruits, ", "))

7. 嵌套表

嵌套表是指表中包含其他表的情况,可以用来表示更复杂的数据结构,如二维数组、树等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
local matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}

print("Matrix:")
for i = 1, #matrix do
local row = matrix[i]
print(table.concat(row, "\t"))
end

-- 访问嵌套表元素
print("Element at (2, 3):", matrix[2][3])

额外示例:嵌套表的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-- 嵌套表的应用:表示一个公司结构
local company = {
name = "Tech Corp",
departments = {
{
name = "Engineering",
employees = {
{name = "Alice", position = "Engineer"},
{name = "Bob", position = "Manager"}
}
},
{
name = "Marketing",
employees = {
{name = "Charlie", position = "Marketer"},
{name = "Diana", position = "Manager"}
}
}
}
}

print("Company name:", company.name)
print("Engineering department employees:")
for _, emp in ipairs(company.departments[1].employees) do
print(" ", emp.name, "-", emp.position)
end

8. 表的拷贝

表的拷贝分为浅拷贝和深拷贝两种方式。

浅拷贝

浅拷贝只复制表的顶层元素,对于嵌套表,只复制引用,不复制其内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 浅拷贝示例
local original = {a = 1, b = {c = 2}}
local copy = {}
for key, value in pairs(original) do
copy[key] = value
end

print("Original.b.c:", original.b.c)
print("Copy.b.c:", copy.b.c)

-- 修改嵌套表,浅拷贝会影响原表
copy.b.c = 100
print("After modifying copy.b.c:")
print("Original.b.c:", original.b.c)
print("Copy.b.c:", copy.b.c)

深拷贝

深拷贝会递归复制表的所有元素,包括嵌套表,创建一个完全独立的副本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 深拷贝函数
function deep_copy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deep_copy(orig_key)] = deep_copy(orig_value)
end
setmetatable(copy, deep_copy(getmetatable(orig)))
else -- 基本类型直接复制
copy = orig
end
return copy
end

-- 使用深拷贝
local deep_copy_table = deep_copy(original)
deep_copy_table.b.c = 200
print("\nAfter deep copy and modifying:")
print("Original.b.c:", original.b.c)
print("Deep copy.b.c:", deep_copy_table.b.c)

额外示例:深拷贝的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
-- 深拷贝的应用:配置对象的复制
local default_config = {
window = {
width = 800,
height = 600,
position = {x = 100, y = 100}
},
sound = {
volume = 0.7,
enabled = true
}
}

-- 创建用户配置,基于默认配置但有一些修改
local user_config = deep_copy(default_config)
user_config.window.width = 1024
user_config.window.height = 768
user_config.sound.volume = 0.9

print("Default window width:", default_config.window.width)
print("User window width:", user_config.window.width)
print("Default sound volume:", default_config.sound.volume)
print("User sound volume:", user_config.sound.volume)

9. 表的元表

元表(Metatable)是 Lua 中一个强大的特性,允许我们修改表的行为,例如定义运算符、访问控制等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local t1 = {1, 2, 3}
local t2 = {4, 5, 6}

-- 设置元表前,+操作会报错
-- print(t1 + t2) -- 错误:attempt to perform arithmetic on a table value

-- 创建元表
local mt = {
__add = function(a, b) -- 定义+操作
local result = {}
for _, v in ipairs(a) do table.insert(result, v) end
for _, v in ipairs(b) do table.insert(result, v) end
return result
end
}

-- 设置元表
setmetatable(t1, mt)
setmetatable(t2, mt)

-- 现在可以使用+操作符连接两个表
local t3 = t1 + t2
print("t1 + t2 =", table.concat(t3, ", "))

额外示例:更多元表操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
-- 定义更多元表操作
local mt = {
-- 算术运算符
__add = function(a, b) return a.value + b.value end,
__sub = function(a, b) return a.value - b.value end,

-- 关系运算符
__eq = function(a, b) return a.value == b.value end,
__lt = function(a, b) return a.value < b.value end,

-- 索引操作
__index = function(table, key)
if key == "double" then
return table.value * 2
end
return nil
end,

-- 新索引操作
__newindex = function(table, key, value)
if key == "value" and type(value) ~= "number" then
print("Error: value must be a number")
return
end
rawset(table, key, value)
end
}

-- 创建带有元表的表
local num1 = {value = 10}
local num2 = {value = 20}
setmetatable(num1, mt)
setmetatable(num2, mt)

print("num1 + num2 =", num1 + num2)
print("num2 - num1 =", num2 - num1)
print("num1 < num2 =", num1 < num2)
print("num1 == num2 =", num1 == num2)
print("num1.double =", num1.double)

-- 测试 __newindex
num1.value = 30
print("num1.value =", num1.value)
num1.value = "not a number" -- 应该报错
print("num1.value =", num1.value)

10. 额外内容:表的长度计算和特殊用法

表的长度计算

在 Lua 中,使用 # 操作符可以获取表的长度,但它只对序列(从 1 开始的连续数值索引)有效。

1
2
3
4
5
6
7
8
9
-- 表的长度计算
local seq = {1, 2, 3, 4, 5}
print("Length of sequence:", #seq) -- 正确:5

local sparse = {1, 2, nil, 4, 5}
print("Length of sparse table:", #sparse) -- 可能返回 2 或 5,取决于实现

local mixed = {1, 2, 3, name = "test", value = 100}
print("Length of mixed table:", #mixed) -- 只计算数组部分:3

表的特殊用法

表作为函数参数

表可以作为函数参数传递,这对于传递多个相关的值非常方便。

1
2
3
4
5
6
7
8
9
-- 表作为函数参数
function print_person(p)
print("Name:", p.name)
print("Age:", p.age)
print("City:", p.city)
end

local person = {name = "John", age = 30, city = "New York"}
print_person(person)

表作为函数返回值

函数可以返回表,这对于返回多个相关的值非常有用。

1
2
3
4
5
6
7
8
9
10
11
-- 表作为函数返回值
function create_person(name, age, city)
return {
name = name,
age = age,
city = city
}
end

local new_person = create_person("Alice", 25, "London")
print("New person:", new_person.name, new_person.age, new_person.city)

表作为模块

在 Lua 中,模块通常使用表来实现,将相关的函数和变量组织在一起。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 表作为模块
local math_utils = {
pi = 3.14159,

add = function(a, b) return a + b end,
subtract = function(a, b) return a - b end,
multiply = function(a, b) return a * b end,
divide = function(a, b)
if b == 0 then return nil, "Division by zero" end
return a / b
end
}

print("math_utils.pi =", math_utils.pi)
print("math_utils.add(10, 5) =", math_utils.add(10, 5))
print("math_utils.divide(10, 2) =", math_utils.divide(10, 2))

运行示例

要运行 tables.lua 文件,只需在命令行中执行:

1
lua tables.lua

运行结果将显示各个部分的输出,包括表的基本操作、遍历、操作函数的使用等。

总结

本教程介绍了 Lua 编程语言中的表操作相关知识,包括:

  • 表的基本概念和创建方式
  • 数组(数值索引表)的使用
  • 字典(字符串索引表)的使用
  • 混合表的特性
  • 表的遍历方法(ipairs 和 pairs)
  • 表操作函数(insert, remove, sort, concat, unpack)
  • 嵌套表的应用
  • 表的浅拷贝和深拷贝
  • 表的元表和元方法
  • 表的长度计算和特殊用法

表是 Lua 中最强大、最灵活的数据结构,掌握表的使用对于 Lua 编程至关重要。通过本教程的学习,您应该已经对 Lua 表的各种操作有了全面的了解,可以在实际编程中灵活运用表来解决各种问题。

tables.lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
-- Lua表操作示例
-- print语句使用英语,注释使用中文

-- 1. 表的基本概念
print("=== Basic Concepts of Tables ===")

-- 空表
local empty_table = {}
print("Empty table:", empty_table)
print("Type of empty_table:", type(empty_table))

-- 2. 数组(数值索引表)
print("\n=== Arrays (Numeric Indexed Tables) ===")

-- 整数索引表,索引从1开始
local fruits = {"apple", "banana", "orange", "grape"}
print("Fruits table:")
print("First fruit:", fruits[1]) -- Lua数组索引从1开始
print("Second fruit:", fruits[2])
print("Number of fruits:", #fruits) -- #操作符获取表长度

-- 手动指定索引
local numbers = {[1] = 10, [2] = 20, [3] = 30}
print("Numbers table:", numbers[1], numbers[2], numbers[3])

-- 3. 字典(字符串索引表)
print("\n=== Dictionaries (String Indexed Tables) ===")

local person = {
name = "John",
age = 30,
city = "New York",
is_student = false
}

print("Person table:")
print("Name:", person.name) -- 点表示法
print("Age:", person["age"]) -- 方括号表示法

-- 添加新键值对
person.occupation = "Engineer"
person["salary"] = 50000
print("Occupation:", person.occupation)
print("Salary:", person.salary)

-- 删除键值对
person.is_student = nil
print("After deleting is_student:", person.is_student)

-- 4. 混合表(同时包含数组和字典部分)
print("\n=== Mixed Tables ===")

local mixed_table = {
"first", -- 索引1
"second", -- 索引2
name = "mixed",
value = 100,
"third" -- 索引3
}

print("Mixed table:")
print("Index 1:", mixed_table[1])
print("Index 2:", mixed_table[2])
print("Index 3:", mixed_table[3])
print("Name:", mixed_table.name)
print("Value:", mixed_table.value)
print("Length of mixed_table:", #mixed_table) -- 只计算数组部分

-- 5. 表遍历
print("\n=== Table Traversal ===")

-- 使用ipairs遍历数组部分(仅遍历数值索引,按顺序)
print("Using ipairs to iterate fruits:")
for index, fruit in ipairs(fruits) do
print("Index", index, ":", fruit)
end

-- 使用pairs遍历整个表(包括数组和字典部分,无序)
print("\nUsing pairs to iterate person:")
for key, value in pairs(person) do
print(key, ":", value)
end

-- 遍历混合表
print("\nUsing pairs to iterate mixed_table:")
for key, value in pairs(mixed_table) do
print(key, ":", value)
end

-- 6. 表操作函数
print("\n=== Table Operations ===")

-- table.insert:在指定位置插入元素
local numbers = {1, 2, 3, 4, 5}
print("Original numbers:", table.concat(numbers, ", "))

table.insert(numbers, 3, 100) -- 在索引3处插入100
print("After table.insert(numbers, 3, 100):", table.concat(numbers, ", "))

table.insert(numbers, 200) -- 在末尾插入200
print("After table.insert(numbers, 200):", table.concat(numbers, ", "))

-- table.remove:删除指定位置的元素
local removed = table.remove(numbers, 3) -- 删除索引3处的元素
print("Removed element:", removed)
print("After table.remove(numbers, 3):", table.concat(numbers, ", "))

removed = table.remove(numbers) -- 删除末尾元素
print("Removed element:", removed)
print("After table.remove(numbers):", table.concat(numbers, ", "))

-- table.sort:排序
local unsorted = {5, 2, 8, 1, 9, 3}
print("\nUnsorted:", table.concat(unsorted, ", "))

table.sort(unsorted)
print("Sorted ascending:", table.concat(unsorted, ", "))

-- 降序排序
table.sort(unsorted, function(a, b)
return a > b
end)
print("Sorted descending:", table.concat(unsorted, ", "))

-- table.concat:连接表元素为字符串
local words = {"Hello", "World", "Lua"}
local sentence = table.concat(words, " ")
print("\nConcatenated string:", sentence)

local numbers_str = table.concat({1, 2, 3, 4, 5}, "-")
print("Concatenated numbers:", numbers_str)

-- table.unpack:将表元素作为可变参数返回
local coords = {10, 20, 30}
local x, y, z = unpack(coords)
print("\nUnpacked coordinates:", x, y, z)

-- 7. 嵌套表
print("\n=== Nested Tables ===")

local matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
}

print("Matrix:")
for i = 1, #matrix do
local row = matrix[i]
print(table.concat(row, "\t"))
end

-- 访问嵌套表元素
print("Element at (2, 3):", matrix[2][3])

-- 8. 表的深浅拷贝
print("\n=== Table Copying ===")

-- 浅拷贝示例
local original = {a = 1, b = {c = 2}}
local copy = {}
for key, value in pairs(original) do
copy[key] = value
end

print("Original.b.c:", original.b.c)
print("Copy.b.c:", copy.b.c)

-- 修改嵌套表,浅拷贝会影响原表
copy.b.c = 100
print("After modifying copy.b.c:")
print("Original.b.c:", original.b.c)
print("Copy.b.c:", copy.b.c)

-- 深拷贝函数
function deep_copy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[deep_copy(orig_key)] = deep_copy(orig_value)
end
setmetatable(copy, deep_copy(getmetatable(orig)))
else -- 基本类型直接复制
copy = orig
end
return copy
end

-- 使用深拷贝
local deep_copy_table = deep_copy(original)
deep_copy_table.b.c = 200
print("\nAfter deep copy and modifying:")
print("Original.b.c:", original.b.c)
print("Deep copy.b.c:", deep_copy_table.b.c)

-- 9. 表的元表(简单示例)
print("\n=== Metatables (Simple Example) ===")

local t1 = {1, 2, 3}
local t2 = {4, 5, 6}

-- 设置元表前,+操作会报错
-- print(t1 + t2) -- 错误:attempt to perform arithmetic on a table value

-- 创建元表
local mt = {
__add = function(a, b) -- 定义+操作
local result = {}
for _, v in ipairs(a) do table.insert(result, v) end
for _, v in ipairs(b) do table.insert(result, v) end
return result
end
}

-- 设置元表
setmetatable(t1, mt)
setmetatable(t2, mt)

-- 现在可以使用+操作符连接两个表
local t3 = t1 + t2
print("t1 + t2 =", table.concat(t3, ", "))