Lua只有一种数据结构,叫table。但是他灰常强大,足以满足我们一般的要求,而且可以根据table做出其他的效果。
一.简介
table类型实际上是一种关联数组,是一种具有特殊索引方式的数组,不仅可以通过整数来索引,还可以通过字符串等其他类型(除了nil)来索引。table没有固定大小,可以动态添加元素。
table可以被理解为一个对象,程序使用一个引用来使用table,这个引用是基于引用计数的。如果一个table没有被引用,那么Lua的垃圾回收机制会清除table并回收其内存。
创建table是通过构造式来创建的。
先来看看传统的C语言的方式的数组用法:
--创建一个table,并将其引用使用a保存
a = {}
--向table中添加三条数据
a[1] = "hehe"
a[2] = "haha"
a[3] = "heihei"
--输出
for i = 1,3 do
print(a[i])
end
结果:hehe
haha
heihei
请按任意键继续. . .
haha
heihei
请按任意键继续. . .
but Lua的数组的索引可以是其他类型的,类似dictionary的功能。下面是使用字符串作为索引:
--创建一个table,并将其引用使用a保存
a = {}
--table中的索引不仅限于number,使用其他类型的数据也可以作为索引
a["hehe"] = "heihei"
local i = "hh"
a[i] = "haha"
local t = "hehe"
print(a[t])
print(a["hh"])
结果:heihei
haha
请按任意键继续. . .
haha
请按任意键继续. . .
一个非常容易出错的地方:
一种简便的写法:a.name <=>a["name"] 千万不要与a[name]搞混
--创建一个table,并将其引用使用a保存
a = {}
a["name"] = "puppet"
print(a.name)
结果:
puppet
a = {}
x = "y"
a[x] = 10
--表示a[x]未定义,为nil
print(a.x)
--表示a["y"],为10
print(a.y)
结果:nil
10
请按任意键继续. . .
10
请按任意键继续. . .
table是匿名的,持有table引用的变量与table自身木有关系。可以有多个变量引用同一个table。当不需要table时,就将这个引用的变量置为nil,当一个table所有的引用都为nil时,那么table就被垃圾回收机制收了。
a = {}
a[1] = "haha"
--b与a引用了同一个table
b = a
print(b[1])
--通过b对table操作等同于通过a对table操作
b[1] = "heihei"
print(a[1])
a = nil
--b还引用着table
b = nil
--现在table被收了
结果:haha
heihei
请按任意键继续. . .
heihei
请按任意键继续. . .
二.table构造式
构造式是用来初始化table的表达式,是Lua特有的也是灰常有用的一种表达式。
最简单的table构造式就是一个空的table:
a = {}
我们也可以将table构造式用于数组的初始化,比如:--table构造式
day = {"Sunday", "Monday", "Tuesday", "Wendesday", "Thursday", "Friday", "Saturday"}
--注意,Lua中数组的开始为1,这一点与C等不同
print(day[1])
print(day[4])
结果:Sunday
Wendesday
请按任意键继续. . .
Wendesday
请按任意键继续. . .
这里要注意的一点:Lua中数组的起始为1,不是0!!!
对于那种非普通数组的table初始化,lua提供了一种比较简单的方式:
对于那种非普通数组的table初始化,lua提供了一种比较简单的方式:
a = {x = "hehe", y = "haha"}
print(a.x)
print(a.y)
结果:hehe
haha
请按任意键继续. . .
上面的构造式相当于下面的一大串:
haha
请按任意键继续. . .
上面的构造式相当于下面的一大串:
a = {}
a.x = "hehe"
a.y = "heihei"
--最麻烦的写法如下:
--a["x"] = "hehe"
--a["y"] = "heihei"
print(a.x)
print(a.y)
三.table的table
table什么都能装,而且同一个table中可以装不同类型的东东:
a = {x = 1, y = "hehe"}
print(a.x)
print(a.y)
结果:1
hehe
请按任意键继续. . .
hehe
请按任意键继续. . .
当然,这不是最牛的,最牛的是table的table:
a = {x = "hehe", y = "heihei"}
b = {i = "haha"}
--将key z value b添加到table a中
a.z = b
--使用:a.z表示b,b.i索引到了“haha”
print(a.z.i)
结果:haha
请按任意键继续. . .
请按任意键继续. . .
当不需要一个字段时,可以将其赋值为nil:
a = {x = "hehe", y = "heihei"}
--当不需要一个字段时,将其赋值为nil
a.x = nil
四.table的遍历
对于数据结构,遍历是最重要的操作了。
1.数组型遍历
对于数组型的table,遍历比较简单。
a = {"Monday", "Tuesday", "Wednesday"}
--#a是取数组或者线性表最后一个索引值
for i = 1, #a do
print(a[i])
end
结果:Monday
Tuesday
Wednesday
请按任意键继续. . .
Tuesday
Wednesday
请按任意键继续. . .
注意:这里说的数组型table,指的是使用number作为索引的那种C类型的数组。如果索引为其他类型,不能用这种方式来遍历。
2.迭代器遍历
对于那种不是传统数组,而是key-value对的table,就需要使用迭代器进行遍历了。
--一个使用字段索引的table
a = {x = "hehe", y = "haha", z = "heihei"}
--使用迭代器进行迭代,每次i被赋予一个新的key,而k则会被赋值成key所对应的value
for i, k in pairs(a) do
print(i, k)
end
结果:y haha
x hehe
z heihei
请按任意键继续. . .
x hehe
z heihei
请按任意键继续. . .
注意,迭代器有几种,在不同的时候需要用不同的迭代器:
用于迭代文件的:io.lines
用于迭代table的:pairs
用于迭代数组元素的:ipairs
用于迭代字符串的单词的:string.gmatch
比如下面用的ipairs迭代传统数组:
a = {"Monday", "Tuesday", "Wednesday"}
--用于迭代传统数组的ipairs迭代器
for i, k in ipairs(a) do
print(k)
end
结果:Monday
Tuesday
Wednesday
请按任意键继续. . .
Tuesday
Wednesday
请按任意键继续. . .