Lua


6.2 表的访问与修改


文档摘要

6.2 表的访问与修改 Lua 表 (Table) 的访问与修改详解 (基于两表场景) 本文将重点关注以下内容: 表的创建与初始化: 了解如何创建空表和带有初始值的表。 表的访问: 掌握使用索引和点号运算符访问表元素的方法。 表的修改: 学习添加、更新和删除表元素的不同方式。 两表操作场景: 探讨在涉及两个表时,常见的访问和修改操作,例如数据传递、合并和关联。 代码实践与详解: 通过丰富的代码示例,深入理解每种操作的原理和应用场景。 1. 表的创建与初始化 在 Lua 中,表使用花括号 来创建。可以创建空表,也可以在创建时初始化表元素。 1.1 创建空表 以上代码分别创建了两个名为 和 的空表。此时,这两个表没有任何元素。 1.2 创建带有初始值的表 可以在创建表时直接赋予初始值。

6.2 表的访问与修改

Lua 表 (Table) 的访问与修改详解 (基于两表场景)

本文将重点关注以下内容:

  • 表的创建与初始化: 了解如何创建空表和带有初始值的表。

  • 表的访问: 掌握使用索引和点号运算符访问表元素的方法。

  • 表的修改: 学习添加、更新和删除表元素的不同方式。

  • 两表操作场景: 探讨在涉及两个表时,常见的访问和修改操作,例如数据传递、合并和关联。

  • 代码实践与详解: 通过丰富的代码示例,深入理解每种操作的原理和应用场景。

1. 表的创建与初始化

在 Lua 中,表使用花括号 {} 来创建。可以创建空表,也可以在创建时初始化表元素。

1.1 创建空表

-- 创建一个空表 local table1 = {} local table2 = {} print(table1) -- 输出:table: 0x...... (表的内存地址,每次运行可能不同) print(table2) -- 输出:table: 0x......

以上代码分别创建了两个名为 table1table2 的空表。此时,这两个表没有任何元素。

1.2 创建带有初始值的表

可以在创建表时直接赋予初始值。Lua 表的初始化方式非常灵活,可以根据需要使用不同的键值对形式。

1.2.1 索引数组式初始化 (列表)

如果你想创建一个类似数组的表,可以使用数字索引进行初始化。Lua 表的索引默认从 1 开始。

local table1 = {10, 20, 30, 40} -- 数字索引,默认从 1 开始 print(table1[1]) -- 输出:10 print(table1[3]) -- 输出:30 print(table1[#table1]) -- 输出:40 (#table1 获取表的长度,即元素个数)

1.2.2 键值对式初始化 (关联数组)

更常见的是使用键值对来初始化表,其中键可以是字符串、数字或其他 Lua 值(除了 nil)。

local table2 = { name = "Alice", age = 30, city = "New York" } print(table2.name) -- 输出:Alice (使用点号运算符访问) print(table2["age"]) -- 输出:30 (使用字符串索引访问) print(table2.city) -- 输出:New York

1.2.3 混合初始化

Lua 表可以同时包含数字索引和字符串键值对,实现更复杂的数据结构。

local table1 = { "apple", -- 索引 1 "banana", -- 索引 2 name = "Charlie", -- 字符串键 "name" age = 25, -- 字符串键 "age" [5] = "grape" -- 数字索引 5 (显式指定索引) } print(table1[1]) -- 输出:apple print(table1.name) -- 输出:Charlie print(table1[5]) -- 输出:grape print(table1[3]) -- 输出:nil (索引 3 没有显式赋值,默认为 nil)

2. 表的访问

访问表元素主要有两种方式:索引访问和点号运算符访问。

2.1 索引访问 []

索引访问是最通用的方式,可以使用数字或字符串作为索引来访问表元素。

2.1.1 数字索引访问

用于访问索引数组式表或混合表中数字索引的元素。

local table1 = {10, 20, 30} print(table1[1]) -- 输出:10 print(table1[2]) -- 输出:20 print(table1[3]) -- 输出:30 print(table1[4]) -- 输出:nil (索引超出范围,返回 nil)

2.1.2 字符串索引访问

用于访问键值对式表或混合表中字符串键对应的元素。

local table2 = { name = "Bob", age = 28 } print(table2["name"]) -- 输出:Bob print(table2["age"]) -- 输出:28 print(table2["city"]) -- 输出:nil (键 "city" 不存在,返回 nil)

2.2 点号运算符访问 .

点号运算符是索引访问的语法糖,只能用于访问字符串键值对,且键必须是合法的 Lua 标识符(字母、数字、下划线,不能以数字开头)。

local table2 = { name = "Bob", age = 28 } print(table2.name) -- 输出:Bob (等价于 table2["name"]) print(table2.age) -- 输出:28 (等价于 table2["age"]) -- 以下情况不能使用点号运算符 local table3 = { ["first name"] = "David", -- 键包含空格,不是合法标识符 ["1st"] = "one" -- 键以数字开头,不是合法标识符 } -- print(table3.first name) -- 错误!语法错误 -- print(table3.1st) -- 错误!语法错误 print(table3["first name"]) -- 正确,使用字符串索引访问 print(table3["1st"]) -- 正确,使用字符串索引访问

2.3 访问不存在的键

当访问表中不存在的键时,Lua 会返回 nil

local table1 = { name = "Eve" } print(table1.name) -- 输出:Eve print(table1.city) -- 输出:nil (键 "city" 不存在) print(table1[2]) -- 输出:nil (数字索引 2 不存在)

3. 表的修改

修改表主要包括添加新元素、更新现有元素和删除元素。

3.1 添加新元素

添加新元素非常简单,只需为表的新键赋值即可。

3.1.1 使用数字索引添加

通常用于向索引数组式表或混合表末尾添加元素。

local table1 = {10, 20} table1[3] = 30 -- 添加到索引 3 table1[4] = 40 -- 添加到索引 4 print(table1[1], table1[2], table1[3], table1[4]) -- 输出:10 20 30 40 print(#table1) -- 输出:4 (表长度已增加)

3.1.2 使用字符串键添加

用于向键值对式表或混合表添加新的键值对。

local table2 = { name = "Frank" } table2.city = "London" -- 使用点号运算符添加 table2["country"] = "UK" -- 使用字符串索引添加 print(table2.name, table2.city, table2.country) -- 输出:Frank London UK

3.2 更新现有元素

更新现有元素与添加新元素语法相同,只需为已存在的键重新赋值即可。

3.2.1 更新数字索引元素

local table1 = {10, 20, 30} table1[2] = 25 -- 更新索引 2 的值 print(table1[1], table1[2], table1[3]) -- 输出:10 25 30

3.2.2 更新字符串键元素

local table2 = { name = "Grace", age = 35 } table2.age = 36 -- 使用点号运算符更新 table2["name"] = "Gina" -- 使用字符串索引更新 print(table2.name, table2.age) -- 输出:Gina 36

3.3 删除元素

要删除表中的元素,需要将对应键的值设置为 nil

3.3.1 删除数字索引元素

将数字索引对应的值设置为 nil 并不会改变表的长度,但会使该索引位置的值变为 nil。如果需要真正移除数字索引元素并调整后续元素的索引,可以使用 table.remove() 函数 (将在后面介绍)。

local table1 = {10, 20, 30, 40} table1[2] = nil -- 删除索引 2 的元素 (实际上是设置为 nil) print(table1[1], table1[2], table1[3], table1[4]) -- 输出:10 nil 30 40 print(#table1) -- 输出:4 (表长度仍然是 4,但索引 2 的值为 nil)

3.3.2 删除字符串键元素

将字符串键对应的值设置为 nil 即可删除该键值对。

local table2 = { name = "Henry", city = "Paris", age = 40 } table2.city = nil -- 删除键 "city" 对应的元素 print(table2.name, table2.city, table2.age) -- 输出:Henry nil 40 print(table2["city"]) -- 输出:nil (键 "city" 已被删除,访问返回 nil)

3.4 table.insert() 函数

table.insert(table, [pos,] value) 函数用于向数组式表中插入元素。

  • table: 要操作的表。

  • pos (可选): 插入位置的索引。如果省略,则在表末尾插入。

  • value: 要插入的值。

当指定 pos 时,table.insert() 会将 pos 位置及其之后的所有元素向后移动一位,然后将 value 插入到 pos 位置。

local table1 = {"apple", "banana", "cherry"} table.insert(table1, "grape") -- 在末尾插入 "grape" print(table1[1], table1[2], table1[3], table1[4]) -- 输出:apple banana cherry grape table.insert(table1, 2, "orange") -- 在索引 2 的位置插入 "orange" print(table1[1], table1[2], table1[3], table1[4], table1[5]) -- 输出:apple orange banana cherry grape

3.5 table.remove() 函数

table.remove(table, [pos]) 函数用于移除数组式表中的元素。

  • table: 要操作的表。

  • pos (可选): 要移除元素的索引。如果省略,则移除表末尾的元素。

当指定 pos 时,table.remove() 会移除 pos 位置的元素,并将 pos 位置之后的所有元素向前移动一位。

local table1 = {"apple", "orange", "banana", "cherry", "grape"} table.remove(table1) -- 移除末尾元素 "grape" print(table1[1], table1[2], table1[3], table1[4]) -- 输出:apple orange banana cherry table.remove(table1, 2) -- 移除索引 2 的元素 "orange" print(table1[1], table1[2], table1[3]) -- 输出:apple banana cherry

4. 两表操作场景

在实际编程中,经常需要操作两个或多个表。以下是一些常见的两表操作场景,并结合访问和修改操作进行说明。

4.1 数据传递:从一个表复制数据到另一个表

场景:假设 table1 存储了一些数据,需要将这些数据复制到 table2

代码示例:

local table1 = { name = "Data Source", items = { "item1", "item2", "item3" }, count = 3 } local table2 = {} -- 创建空表 table2 -- 复制 table1 的所有键值对到 table2 for key, value in pairs(table1) do table2[key] = value end print("Table 1:") for k, v in pairs(table1) do print(k, v) end print("\nTable 2 (after copy):") for k, v in pairs(table2) do print(k, v) end -- 修改 table2 中的数据,table1 不受影响 (浅拷贝) table2.name = "Data Destination" table2.items[1] = "new item1" print("\nTable 1 (after table2 modification):") for k, v in pairs(table1) do print(k, v) end print("\nTable 2 (after modification):") for k, v in pairs(table2) do print(k, v) end

代码详解:

  • 使用 pairs(table1) 迭代 table1 的所有键值对。

  • table1 的每个键值对赋值给 table2,实现数据的复制。

  • 注意: 这种复制是浅拷贝。如果表的值本身是另一个表(例如 items 字段),则 table2 中的 items 仍然指向 table1items 的同一个表。修改 table2.items 内部的元素会影响 table1.items。如果要进行深拷贝,需要递归复制嵌套的表。

4.2 表的合并:将两个表合并为一个表

场景:有两个表 table1table2,需要将它们合并成一个新的表 mergedTable

代码示例:

local table1 = { a = 1, b = 2, c = 3 } local table2 = { d = 4, e = 5, f = 6, a = 100 } -- 注意键 'a' 在 table2 中也存在 local mergedTable = {} -- 将 table1 的数据复制到 mergedTable for key, value in pairs(table1) do mergedTable[key] = value end -- 将 table2 的数据复制到 mergedTable for key, value in pairs(table2) do mergedTable[key] = value -- 如果键已存在,table2 的值会覆盖 table1 的值 end print("Table 1:") for k, v in pairs(table1) do print(k, v) end print("\nTable 2:") for k, v in pairs(table2) do print(k, v) end print("\nMerged Table:") for k, v in pairs(mergedTable) do print(k, v) end

代码详解:

  • 创建一个空表 mergedTable

  • 遍历 table1table2,将它们的键值对都复制到 mergedTable

  • 注意: 如果两个表中存在相同的键,后复制的表 (table2 在本例中) 的值会覆盖先复制的表 (table1) 的值。例如,键 'a'mergedTable 中的值会是 100 (来自 table2) 而不是 1 (来自 table1)。

4.3 表的关联:根据一个表的数据修改另一个表

场景:假设 table1 存储了学生 ID 和姓名,table2 存储了学生 ID 和成绩。需要根据 table1 的学生 ID,在 table2 中查找对应的学生并添加姓名信息。

代码示例:

local table1 = { -- 学生 ID 和姓名 [1001] = "Alice", [1002] = "Bob", [1003] = "Charlie" } local table2 = { -- 学生 ID 和成绩 [1001] = 90, [1002] = 85, [1004] = 95 -- 学生 ID 1004 不在 table1 中 } -- 遍历 table2,根据学生 ID 从 table1 中查找姓名并添加到 table2 for studentID, score in pairs(table2) do local name = table1[studentID] -- 在 table1 中查找学生 ID 对应的姓名 if name then table2[studentID] = { name = name, score = score } -- 更新 table2 的值为包含姓名和成绩的表 else table2[studentID] = { name = "Unknown", score = score } -- 如果 table1 中没有找到,姓名设置为 "Unknown" end end print("Table 1 (Student Names):") for k, v in pairs(table1) do print(k, v) end print("\nTable 2 (Scores with Names):") for k, v in pairs(table2) do print(k, v) end

代码详解:

  • 遍历 table2 的每个学生 ID 和成绩。

  • 使用学生 ID 作为键在 table1 中查找对应的姓名。

  • 如果在 table1 中找到姓名,则更新 table2 中对应学生 ID 的值,将其修改为一个包含 namescore 两个字段的表。

  • 如果在 table1 中没有找到姓名(例如学生 ID 1004),则将姓名设置为 "Unknown"。

  • 这种关联操作常用于数据整合和信息补充。

5. 总结

Lua 的表是极其灵活和强大的数据结构,掌握表的访问和修改是 Lua 编程的基础。本文详细介绍了表的创建、初始化、访问和修改方法,并通过两表操作的场景示例,展示了表在实际应用中的灵活性。

核心要点回顾:

  • 表创建: 使用 {} 创建空表或初始化表。

  • 表访问: 使用 [] 索引访问 (数字或字符串索引),使用 . 点号运算符访问 (字符串键,合法标识符)。

  • 表修改: 添加/更新元素:直接赋值 table[key] = valuetable.key = value。 删除元素:设置 table[key] = nil。 使用 table.insert()table.remove() 操作数组式表。

  • 两表操作: 数据传递(浅拷贝),表合并(键冲突处理),表关联(根据一个表修改另一个表)。

通过本文的学习和实践,相信你已经对 Lua 表的访问和修改有了更深入的理解。在实际编程中,灵活运用表,可以构建各种复杂的数据结构和高效的算法。继续探索 Lua 表的更多高级特性,例如 metatable 和面向对象编程,将进一步提升你的 Lua 编程能力。


发布者: 作者: 转发
评论区 (0)
U