【Lua程序设计】Table表

【Lua程序设计】Table表

Table是Lua语言中最主要和强大的数据结构(确实)。可以表示很多的数据结构,包括但不限于数组,集合,字典,链表。实现面向对象也是通过使用表(后续再写)。对于Lua语言提供的原生的函数库其实也是表,表中包含提供给我们使用的函数,当进行对应的函数调用时其实就是调用对应表中的函数。全局变量实际也存储在表( Global)中。
可以将表看做是一个字典,其中的key可以为任意的有效值(非nil),value也可以为任意有效值(非nil),Dictionary<object,object>。
书中原句:Lua语言中的表要么是值要么是变量,它们都是对象。可以认为,表是一种动态分配的对象,程序只能操作指向表的引用(或指针)。除此以外,Lua语言不会进行隐藏的拷贝(深拷贝)或创建新的表。(这里书上的注解感觉也有问题说的有点不够明白,其实意思就是Lua语言不会给你复制一份值再赋值过去(深拷贝),而只是进行浅拷贝(引用),所以修改一个表中的值,对应的指向该表的对象也会发生更改)

--表是 {1,2,3,4},a变量是指向表的引用
a = {1,2,3,4}
c = {5,6,7,8,9}
--将a赋值给b,a指向的表发生改变时b对应的也会变化
b = a
--将a['c']赋值为c,c其实是表的引用,当c指向的表发生改变时a['c']也会有对应的更改
a.c = c
--修改表中值
c[1] = 10
--输出了1 10...
for k,v in pairs(a.c) do
    print(k,v);
end

c[2] = 11
--输出了1 10,2 11...
for k,v in pairs(b.c) do
    print(k,v);
end

5.1表索引

同一个表中存储的值可以具有不同的类型索引,可以是数字,字符串,函数,bool值,表等,并可以按需增长以容纳新元素。

function test()
	print("test")
end
--声明一个空表
a={}
--声明一个包含一个值的表键值对为[1,1]
b ={1}
--给a中添加新元素
a[test] = "test:function"
a[b] = "b:table"
a[1.1] = "float"
a["1.2"]="string"
a[false] = "假"
for k,v in pairs(a) do
    print(k,v)
end
--[[结果如下
table: 00000000006e9400 b:table
1.1     float
function: 00000000012104c0      test:function
false   鍋
1.2     string
]]

表中为定义的元素值为nil,将nil值赋值给表元素可以将其删除。当把表当做结构体使用时,可以把索引当做成员名称使用,即使用a.name表示为a[“name”],简化代码。
但是不要混用a.name和a[name],a.name代表的是索引为字符串"name"的表值即a[“name”],a[name]则表示的是索引为name变量。所以a[0]和a[“0”]是不同的意思。
那么对于数值索引中的浮点型值和整数值会不会也不一样呢?答案是当索引是number类型时,两个相等的索引值指向的值是相同的,即5和5.0指向的是同一个值。更准确的说,当被用作表索引时,任何能被转换为整型值的浮点数都会被转换为整型数。

a={};
name = "myname"
a.name = "name string"
--name值为"myname"所以这里其实相当于a["myname"]="myname in table",所以a.myname才能输出
a[name] = "myname in table"
print(a.name,a[name],a.myname)
--不存在的索引输出nil
print(a.b)
a[5] = "number int 5"
print(a[5.0])
--[[结果
name string   myname in table   myname in table
nil
number int 5
]]

5.2表构造器

表构造器是用来创建和初始化表的表达式。最简单的构造器就是空构造器{}。
表构造器可以用来初始化列表(这里的列表就是索引值逐渐递增的表,类似于数组),如下中list[1]=1(构造器的第一个值的索引是从1开始而不是0)

list = {1,2,3,4,5,6,7,8}

Lua语言还提供了一种初始化记录式表的特殊语法

a = {name = "myname",age = 18,height = 180,weight = 75}
--相当于a.name = "myname",a.age = 18,a.height = 180,a.weight = 75

还可以使用一种更加通用的构造器,即用方括号将索引括起来显示的指定每一个索引

a = {["name"] = "myname",["age"] = 18,["height"] = 180,["weight"] = 75}
--和上一个意思相同

在同一个构造器中这几种写法可以混用,同时构造器中可以嵌套构造器,即表中嵌套表。
对于前两种构造器而言是存在局限的,第一种表示的是列表,索引是从1开始逐渐增长的不能是其他值,第二种表示方式索引限制为字符了,第三种方式索引可以为任意值,较为灵活。

5.3数组、列表和序列

如果想要用表来表示数组、列表,那么只需要使用整型作为索引的表即可。一般在Lua语言中索引是从1开始的。
如果想要表示字典那么只需要限制索引类型和值类型为某一种即可。

当操作列表时,往往需要获取到列表的长度。列表的长度可以存放在常量中,也可以存放在其他变量或数据结构中,一般我们会使用索引"n"来存储列表的长度。
我们把所有元素都不为nil的数组称为序列。例如1,2,3,4,5,6,7
我们也可以使用长度操作符 # 获取序列的长度(一定要是序列)。但是我测试的时候发现可以存在空洞(即中间有值为nil)但是只能是一个空洞,就像测试中11为nil时长度还是12,但是13,14都为nil时就不会再看15了不知道是后续更新优化了长度计算符的原因还是怎么回事,大家以测试为准,就是说可以在序列中空一个空洞。

--定义一个长度为10的序列
a = {1,2,3,4,5,6,7,8,9,10}
--10
print(#a)
--a={1,2,3,4,5,6,7,8,9}
a[#a] = nil
--9
print(#a)
--a={1,2,3,4,5,6,7,8,9,11}
a[#a + 1] = 10
--10
print(#a)
---[[
a[12] = 12
--12
print(#a)
a[15] = 15
--12
print(#a)
--]]
a[10000] = 10000
--12
print(#a)
for k,v in pairs(a) do
    print(k,v);
end

5.4遍历表

我们可以使用pairs,或ipairs迭代器遍历表中的键值对,用法已经在前面的实例中有了,就不做其他。这里说下两种遍历的区别。pairs会将所有的键值对都遍历出来,但是是无序的也就是说顺序可能每次都不同。ipairs只会按顺序去遍历表,索引从1开始直到某个索引值为nil停止,好处是顺序固定,坏处是不能把所有的键值对都遍历出来,但是也可以实现单一的列表功能,同时可以在列表中加入"n"索引而不背遍历到。

--接上一个代码块的代码
for k,v in ipairs(a) do
    print(k,v);
end
--[[输出:可以看到因为a[11]为nil后续的都不在输出了
1       1
2       2
3       3
4       4
5       5
6       6
7       7
8       8
9       9
10      10
]]

5.5安全访问

由于表中可以嵌套表,所以可能会出现a.b.c.d.e.f这样的嵌套获取值,但是可能会出现中间某个值为nil导致出现严重错误。在C#中可以使用"?."操作符,例如a?.b,当a为null时,其不会做任何事。但是Lua中是没有这样的安全操作符。
我们可以采用如 value = ((a or {}).b or {})这样来实现一个安全的访问。虽然可能会有很多的括号嵌套,但是减少了表的访问次数,并且是安全的。

5.6表标准库

表标准库提供了操作列表和序列的一些常用函数。

a = {5,10}
for k,v in ipairs(a) do
    print(k,v);
end
--[[
table.insert(table,index,value)||table.insert(table,index = #table+1,value)
在table的index位置插入value值
当没有index时默认插入在最后
]]
table.insert(a,1,0)
for k,v in ipairs(a) do
    print(k,v);
end

for i = #a,#a+2 do
	table.insert(a,111)
end
for k,v in ipairs(a) do
    print(k,v);
end
--[[
table.remove(table,index)||table.remove(table,index = #table+1)
在删除table的index位置,并将其后面的值向前移动
当没有index时默认删除最后的值
]]
table.remove(a,2)
for k,v in ipairs(a) do
    print(k,v);
end
table.remove(a)
for k,v in ipairs(a) do
    print(k,v);
end

下面这个函数我库中也是没有,没有测试过
对于移动表中的元素还引入了一个函数table.move(a,f,e,t)调用该函数可以将表a从索引f到e的元素(包含索引f和索引e对应的元素本身)移动到位置t上。move实际上是将一个值从一个地方拷贝到另一个地方。
table.move(a,1,#a,1,{})返回列表a的一个克隆,当包含另一个表作为参数是,该函数将第一个表中的元素移动到第二个表中的t位置上。

5.7练习(暂无)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值