4. Lua:列表#

本节我们来了解稍微复杂一点的数据类型—— 列表 (亦可称为数组)。

列表由一系列按特定顺序排列的元素组成。你可以创建包含字母表中所有字母、数字0~9或所有家庭成员姓名的列表;也可以将任何东西加入列表中,其中的元素之间可以没有任何关系。 鉴于列表通常包含多个元素,给列表指定一个表示复数的名称(如letters、digits或names)是个不错的主意。

在Lua中,用花括号( {} )来表示列表,并用逗号来分隔其中的元素。 下面是一个简单的列表示例,这个列表包含几名武将:

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
print(generals)

如果直接想用print把列表打印出来的话,Lua大概会打印出这种:

table: 0x560c60b32e40

后面那一串数字每次运行都会有不同。鉴于这不是你要让用户看到的输出,下面来学习如何访问列表元素。

4.1. 访问列表元素#

列表是有序集合,因此要访问列表的任何元素,只需将该元素的位置或索引告诉Lua即可。 要访问列表元素,可指出列表的名称,再指出元素的索引,并将其放在方括号内。

例如,下面的代码从列表generals中提取第一名武将:

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
print(generals[1])  -- 打印出“徐盛”

在Lua中,第一个列表元素的索引为1,而不是0。这倒是很符合人的直觉, 不过对于已经了解过其他编程语言的人可能不是很友好,因为大多数编程语言列表下标都是从0开始。

依此类推,第二个列表元素的索引为2。根据这种简单的计数方式,要访问列表的任何元素, 都利用将其位置作为索引。例如下面的代码打印出generals列表的第2个和第4个:

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
print(generals[2])  -- 打印出“黄忠”
print(generals[4])  -- 打印出“郭嘉”

你也可以新建一个变量来保存列表中取出的某个值:

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
local huangzhong = generals[2]
print(huangzhong)  -- 打印出“黄忠”

4.2. 修改、添加和删除元素#

你创建的大多数列表都将是动态的,这意味着列表创建后,将随着程序的运行增删元素。 例如,当一名角色阵亡时,就要从保存所有存活角色的那个列表删除掉他。

4.2.1. 修改列表元素#

修改列表元素的语法与访问列表元素的语法类似。要修改列表元素,可指定列表名和要修改的元素的索引,再指定该元素的新值。

还是用上面的例子:

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
generals[1] = "界徐盛"
print(generals[1])  -- 因为generals的第一个元素已经被修改了,所以打印出“界徐盛”

就像修改变量的值那样,用一个等号也可以修改列表中对应那个索引的值。

4.2.2. 往列表添加元素#

4.2.2.1. 在列表末尾添加元素#

在列表中添加新元素时,最简单的方式是将元素附加到列表末尾。给列表附加元素时, 它将添加到列表末尾。继续使用前一个示例中的列表,在其末尾添加新元素"张飞":

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
table.insert(generals, "张飞")  -- [1]
print(generals[3])  -- 甘宁
print(generals[5])  -- 张飞

[1]处的代码使用了函数table.insert来将新元素“张飞”添加到了列表generals的末尾。

善用table.insert的话,我们可以轻易的动态创建一个列表。这意思是说,我们先创建一个空列表, 然后可以用 table.insert 向列表不断完善元素:

local generals = {}
table.insert(generals, "徐盛")
table.insert(generals, "黄忠")
table.insert(generals, "甘宁")
table.insert(generals, "郭嘉")
table.insert(generals, "张飞")
print(generals[2]) -- 黄忠

这种创建列表的方式极其常见,因为经常要等程序运行后,你才知道程序会存储哪些数据, 比如要获得一个存储着“所有已受伤角色”的列表,就要从零开始创建,首先创建一个空列表, 然后扫描所有的角色,如果他受伤了,就把他添加到列表中。

4.2.2.2. 在列表中间添加元素#

使用函数 table.insert 还可在列表的任何位置添加新元素。为此,你需要指定新元素的索引和值。

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
table.insert(generals, 1, "张飞")  -- [1]
print(generals[3])  -- 黄忠
print(generals[5])  -- 郭嘉

注意[1]处的代码,他指明了新元素“张飞”应该插入到位置1上,于是Lua先把位置1以及后面的所有元素往右边挪一个位置,空出一个地方后再插入新元素,插入后的列表如下:

{ "张飞", "徐盛", "黄忠", "甘宁", "郭嘉" }

4.2.3. 从列表中删除元素#

4.2.3.1. 在列表末尾删除元素#

table.insert 一样,使用 table.remove 即可删除列表的最后一个元素:

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
table.remove(generals)  -- [1]
print(generals[4])  -- nil

[1]处的代码使用 table.remove ,删除了列表generals的最后一个元素, 所以我们再次试图用4去取的时候就会发现是 nil 了。

4.2.3.2. 确定列表的长度#

上面的代码中,就算我们删除了一个元素也无法很直观的看穿;如果能知道长度就好了, 删除一个元素长度就减少1,增加一个元素长度就加1,那不是很好吗?

在Lua中,我们使用井号( # )来获取列表的长度。用法很简单,在列表名字前面加个井号即可:

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
print(#generals) -- 4
table.remove(generals)
print(#generals) -- 3

4.2.3.3. 删除任意位置的元素#

table.insert 类似, table.remove 亦可用于删除任何一个位置的元素, 只要你把要删除的位置告诉他就行了:

local generals = { "徐盛", "黄忠", "甘宁", "郭嘉" }
table.remove(generals, 1)
print(generals[2])   -- 甘宁

这里删除了列表的1号元素“徐盛”,产生了一个空位,Lua就会自动把后面的元素都左移一位来补齐了; 这也就是说,删除了“徐盛”后,列表就变成了 { "黄忠", "甘宁", "郭嘉" } ,因此再访问2号元素就会得到甘宁。

备注

Lua对于列表的操作基本就这些,新月杀为了易用性又添加了更多的操作办法。 不过因为这里只是对Lua本身的功能进行讲解,所以我们到后面再来看更多更方便的办法吧。