表是Lua中最重要且唯一的数据结构,它可以用来实现数组、字典、对象等多种编程概念。本章将深入探讨表的各种用法和特性。

4.1 表的创建和访问

表是Lua中用于存储各种值的容器,类似于其他语言中的数组或字典。

创建表

使用花括号 {} 来创建表:

  1. local emptyTable = {}
  2. local simpleTable = {10, 20, 30}
  3. local mixedTable = {10, "hello", true, {1, 2}}

你也可以使用键值对创建表:

  1. local person = {
  2. name = "Alice",
  3. age = 30,
  4. ["favorite color"] = "blue"
  5. }

访问表元素

有两种主要方式访问表元素:

  1. 使用点号(对于有效标识符的键):
  1. print(person.name) -- 输出: Alice
  1. 使用方括号(适用于所有类型的键):
  1. print(person["age"]) -- 输出: 30
  2. print(person["favorite color"]) -- 输出: blue

表的动态性质

表是动态的,你可以随时添加或删除元素:

  1. person.job = "Engineer" -- 添加新元素
  2. person.age = nil -- 删除元素

4.2 表作为数组

在Lua中,数组实际上就是以连续整数为键的表。

创建和使用数组

  1. local fruits = {"apple", "banana", "orange"}
  2. print(fruits[1]) -- 输出: apple(注意:Lua的数组索引默认从1开始)

获取数组长度

使用 # 操作符获取数组长度:

  1. print(#fruits) -- 输出: 3

处理稀疏数组

Lua允许创建”洞”在数组中,这称为稀疏数组:

  1. local sparseArray = {1, nil, 3, 4}
  2. print(#sparseArray) -- 输出可能不如预期,因为nil值的存在

4.3 表的遍历技巧

使用 pairs() 遍历表

pairs() 函数用于遍历表的所有键值对:

  1. for key, value in pairs(person) do
  2. print(key, value)
  3. end

使用 ipairs() 遍历数组部分

ipairs() 函数用于遍历数组部分(连续的数字索引):

  1. for index, value in ipairs(fruits) do
  2. print(index, value)
  3. end

自定义遍历顺序

如果你需要特定的遍历顺序,可以先收集和排序键:

  1. local keys = {}
  2. for k in pairs(person) do table.insert(keys, k) end
  3. table.sort(keys)
  4. for _, k in ipairs(keys) do
  5. print(k, person[k])
  6. end

4.4 表操作函数

Lua提供了一些内置函数来操作表。

table.insert() 和 table.remove()

添加和删除元素:

  1. table.insert(fruits, "grape") -- 在末尾添加
  2. table.insert(fruits, 2, "pear") -- 在指定位置插入
  3. local removed = table.remove(fruits) -- 移除并返回最后一个元素
  4. local removed2 = table.remove(fruits, 2) -- 移除并返回指定位置的元素

table.sort()

对表进行排序:

  1. table.sort(fruits) -- 默认按字母顺序排序
  2. -- 自定义排序
  3. table.sort(fruits, function(a, b) return #a < #b end) -- 按长度排序

table.concat()

连接数组元素:

  1. local joined = table.concat(fruits, ", ")
  2. print(joined) -- 输出: apple, banana, orange, grape

4.5 元表基础

元表允许你自定义表的行为。

设置和获取元表

  1. local t = {}
  2. local mt = {}
  3. setmetatable(t, mt)
  4. local mt2 = getmetatable(t)
  5. print(mt == mt2) -- 输出: true

__index 元方法

__index 元方法用于查找不存在的键:

  1. mt.__index = function(table, key)
  2. return "Not found: " .. key
  3. end
  4. print(t.foo) -- 输出: Not found: foo

__newindex 元方法

__newindex 元方法用于拦截新索引的赋值:

  1. mt.__newindex = function(table, key, value)
  2. print("Assigning", key, "=", value)
  3. rawset(table, key, value)
  4. end
  5. t.bar = 10 -- 输出: Assigning bar = 10

使用元表实现简单的面向对象编程

  1. local function createPerson(name)
  2. local person = {name = name}
  3. local mt = {
  4. __index = {
  5. introduce = function(self)
  6. print("My name is " .. self.name)
  7. end
  8. }
  9. }
  10. setmetatable(person, mt)
  11. return person
  12. end
  13. local alice = createPerson("Alice")
  14. alice:introduce() -- 输出: My name is Alice

练习

  1. 创建一个表示学生的表,包含姓名、年龄和成绩。实现一个函数来计算所有学生的平均成绩。
  2. 实现一个简单的购物车系统,可以添加商品、移除商品、计算总价。
  3. 使用元表创建一个简单的向量类,支持向量加法和标量乘法。

通过本章的学习,你应该能够熟练使用Lua的表来组织和操作数据,这为后续更复杂的编程任务打下了基础。

在下一章中,我们将探讨Lua的模块和包管理系统。