表
表是一种动态分配的对象,只能操作指向表的引用,除此之外Lua语言不会进行隐藏的拷贝和创建新的表。
a= {}
k="x"
a[k]=10
a[20]=100
print(a[20])
--表永远是匿名的1,表本身与保存表的变量之间没有固定的关系
b=a
b["x"]=200
print(a["x"])
-- 当不再有引用指向表时,垃圾回收机制会删除这个表,并重新利用其占用的内存。
b=nil
a=nil
--输出
100
200
表索引
表可以使用不同类型的值作为索引。
a={}
a[10]=10
a["x"]=5
--未初始化的值为nil ,将nil赋值给表元素即可将其删除。
print(a["y"])
print(a["x"])
a["x"]=nil
print(a["x"])
当把表作为结构体使用时,有两种形式访问表元素,一般的字符串索引形式和点分形式。
点分形式:可以把索引当做成员名称使用(a.name等价于a[“name”])
a={}
a.x=10 --等价于 a["x"]=10
print(a.x)
print(a.y)
--输出
10
nil
一般用a.x点分形式说明表被当做结构体使用,此时表由固定,预先定义的键组成的集合,而字符串索引形式a[“x”]是表的一般用法
注:a.x 等价于a[“x”] 不等于a[x].
整型和浮点类型的索引时,2与2.0的值相同,他们作为索引时指向同一个元素。
a={}
a[2.0]=10
a[2.1]=100
print(a[2])
print(a[2.1])
--输出
10
100
当被用作表索引时,能够转换为整型的浮点数都会被转化为整型,即2.0可以,而2.1不行。
表构造器
用来创建和初始化表的表达式。
--1.最简单的空构造器
a={}
--2.初始化列表形式(则b[1]="A",注意从1开始)
b={"A","B","C","D"}
print(b[4])
--3.初始化记录式
c={x=10,y=20} --等价于c={}; c.x=10;a.y=20 前者速度更快
print(c["x"])
--输出
D
10
在同一个构造器中,可以混用记录式和列表式写法:
line ={
clolor="red",
thickness=2,
npoints=4,
{x=0,y=1}, --line[1]
{x=1,y=1}, --line[2]
{x=3,y=1}, --line[3]
{x=4,y=1} --line[4]
}
--同时,也展示了表嵌套的用法
print(line[1].x)
print(line[1]["y"])
--输出
0
1
这两种构造方式的局限性:列表式不能使用负数索引(从1开始),记录式只能使用符合标识符规范的标识符。
m={_a=12}
m={_2=12}
m={a=12}
-- m={2=12} 不符合标识符规范
对此,可以使用更加通用的构造器,即通过方括号括起来的表达式显式指定每一个索引。
a={["+"]="add",["-"]="sub"}
print(a["+"])
i=-10
s="-"
b={[i+0]=s,[i+1]=s..s,[i+2]=s..s..s}
print(b[-8])
c={x=0,y=0}--等价于{["x"]=0,["y"]=0}
d={"r","g","b"}--等价于{[1]="r",[2]="g",[3]="b"}
--输出
add
---
数组(列表)和序列
表只要使用整型作为索引,即可作为常见的数组,一般Lua中惯例是从1开始。序列是指由指定n个正整数值类型的键所组成集合{1,…n}形成的表。特别地,不包含数值类型索的表的长度为0的序列。同样使用#获取序列长度。
a={"1","2","3","4"}
print(#a)
b={}
b[1]=1
b[2]=2
print(#b)
c={}
c[2]=2
c[3]=3
print(#c)
--对于存在空洞(nil),长度操作符不可靠 这种情况下 应该存储在一个非数值键字段中,如c["n"]
d={}
d[1]=1
d[2]=2
d[4]=4
d[5]=5
print(#d)
e={}
e[1]=1
e[2]=2
e.age=4
e.name="XXX"
print(#e)
--输出
4
2
0
5
2
遍历表
--1.使用pairs遍历一般的表,但每次遍历顺序不确定
t1={10,"abc",x=11,y=12}
for k,v in pairs(t1) do
print(k,v)
end
--2.使用ipairs遍历序列(即不存在空洞(nil)的数组)
print(".......................")
t2={"abc",2.5,4}
for k,v in ipairs(t2) do
print(k,v)
end
--非序列 即不是从1..n的键,不能这样遍历,只会遍历从1开始有序的部分
print(".......................")
t3={"abc",2.5,[4]=4}
for k,v in ipairs(t2) do
print(k,v)
end
--3.序列的第二种遍历方式
print(".......................")
t4={10,20,"abc",2.5}
for k=1,#t4 do
print(t4[k])
end
--输出
1 10
2 abc
y 12
x 11
.......................
1 abc
2 2.5
3 4
.......................
1 abc
2 2.5
3 4
.......................
10
20
abc
2.5
安全访问
当不确定是否存在某个库,以及某个库中是否存在某个函数可能需要如下写法:
--是否存在函数时
if lib.foo then..
--是否存在库,以及是否存在函数
if lib and lib.foo then..
当很长时很麻烦,采用:
--利用lua or性质,以及表中不存在某个键时返回nil
zip =(((company or {}).director or {}).adress or {}).zipcode
--进一步简化
E={}
zip =(((company or E).director or E).adress or E).zipcode
表标准库
用于操作序列(书里面列表和序列概念较为混乱)
- table.insert(t,[index,]value) :向序列t的指定位置index插入一个元素value,其他元素依次后移,不指定位置时,插入到最后。
- table.remove(t[,index]) :删除并返回序列指定位置的元素,然后将其后的元素移动填充删除元素后造成的空洞。若不指定位置则删除最后一个元素。
- table.move(t,start,end,index,[another table]):将表t中从索引start开始到end的元素,移动(或者说复制,因为原位置并未删除)到位置another table的位置index上。未指定another table则在原表上移动。
a={1,2,3}
print("..........")
for k,v in ipairs(a) do
print(k,v)
end
--insert
table.insert(a,2,5)
print("..........")
for k,v in ipairs(a) do
print(k,v)
end
--remove
table.remove(a,2)
print("..........")
for k,v in ipairs(a) do
print(k,v)
end
--move 带参数
t={}
table.move(a,2,3,1,t)
print("..........")
for k,v in ipairs(t) do
print(k,v)
end
--move 不带参数
t={}
table.move(a,2,3,1)
print("..........")
for k,v in ipairs(a) do
print(k,v)
end
--显然此是复制效果,所以a[3]还在,所以如果要删除则主动
--a[3]=nil
--输出
..........
1 1
2 2
3 3
..........
1 1
2 5
3 2
4 3
..........
1 1
2 2
3 3
..........
1 2
2 3
..........
1 2
2 3
3 3