网站建设php怎么安装,深圳建一个网站要多少钱,天美传媒传媒官网免费下载,给公司做网页收多少钱文章目录 官方唯一指定数据结构--tabletable的一万种用法字典和数组 迭代器ipairs()pairs() 回到Table 在【Lua学习笔记】Lua入门中我们讲到了Lua的一些入门知识点#xff0c;本文将补充Lua的一些进阶知识 官方唯一指定数据结构–table
在上篇文章的最后#xff0c;我们指出… 文章目录 官方唯一指定数据结构--tabletable的一万种用法字典和数组 迭代器ipairs()pairs() 回到Table 在【Lua学习笔记】Lua入门中我们讲到了Lua的一些入门知识点本文将补充Lua的一些进阶知识 官方唯一指定数据结构–table
在上篇文章的最后我们指出通过查询_G的字符索引发现table.insert实际上是一个名为table的table结构里的索引指向的函数
实际上不仅它所有的函数模块全局变量元表 都 是 T A B L E 我不知道作者是出于什么样的心理活动写出的Lua但确实让我这个初学者大为震撼。
(以下内容摘抄自Lua语言基础知识) 但是作为Lua中唯一的数据结构table还是很万能的
它可以用任何类型作索引不止number和string也可以使用其他类型甚至function和tableTable功能强大它即可以用作字典也可以用作数组配合元表机制还可以模拟面向对象。Lua的很多基础设施比如模块全局变量元表都是基于table实现的。
table的一万种用法
字典和数组
-- 当成字典使用
local t {a 1,b true,c abc,
}
-- 当成数组使用
local t2 {1, aa, false}
这两种都是很自然的用法既能作为字典又能作为数组但是它也可以同时表示字典和数组
local t3 {1, 2, 3,a aaa,b bbb,
}
print(t3[1])
print(t3.a)
结果
1
aaa
需要注意的是其中的数组和字典是以两种不同的方式存储的local t3 {a aaa,1, 2,b bbb,3
}
print(t3.a)
print(t3[1])
print(t3[3])
结果
aaa
1
3
从上述例子我们能看到数字索引直接访问了数组元素略过了键值对
使用键值对的key名才能访问字典中对应的值
使用下列模式使得它们在格式上更通用
local t3 {[1] 1, [2] 2, [3] 3,[a] aaa,[b] bbb,
}但是上述只是个例子在实践中我们最好不混用字典和数组这常常会引发混乱的问题。而从设计的角度看它违反了单一职责原则比如空Table就存在着二义性如果它是空的那么请问这种情况下它是数组还是字典这往往会导致使用时的各种问题例子请看下文迭代器。 迭代器
虽然迭代器并不属于Table的知识但我认为在此处插入讲一下是比较合适的。主要就是pairs和ipairs的区别
ipairs()
返回三个值迭代函数、表 t 以及 0 如此以下代码 for i,v in ipairs(t) do body end将迭代键值对 1,t[1]) (2,t[2]) ... 直到第一个空值。 例子
local tab {23,35,[3] 45,78,[8] 101,nil,80
}for k,v in ipairs(tab) doprint(k..:..v)
end
输出
1:23
2:35
3:78
在上述例子中ipairs遍历了数组但在nil时停下实际上这个table的结构应该是这样
local tab: {[1]: integer 23,[2]: integer 35,[3]: integer 45|78,[4]: nil,[5]: integer 80,[8]: integer 101,
}来个更混乱的例子
local tab {23,35,[3] 45,78,[a] 5,[8] 101,[3] nil,1212,nil,80,[b]nil
}for k, v in ipairs(tab) doprint(k .. : .. v)
end
输出
1:23
2:35
3:78
4:1212这是它的实际结构
local tab: {[a]: integer 5,[b]: nil,[1]: integer 23,[2]: integer 35,[3]: integer|nil 45|78,[4]: integer 1212,[5]: nil,[6]: integer 80,[8]: integer 101,
}可以看出ipair只会遍历数字key名的元素也就是数组类型并且当碰到nil时停下而其他字典类型会被无视
而ipair会有三个返回值分别是迭代函数表index。让我们看看这三个值在迭代器中是如何迭代的
print(---index0---)
funcA ,table, index ipairs(tab)
for k, v in funcA, table, index doprint(k .. : .. v)
end
print(---index1---)
for k, v in funcA, table, index1 doprint(k .. : .. v)
end输出
---index0---
1:23
2:35
3:78
4:1212
---index1---
2:35
3:78
4:1212从上述例子中可以看到index实际上代表了起始序列当index0对应从table的数组标签[1]开始当index1,则从[2]开始
如果数组里有负数和0呢
local tab {[0] 1,2,[-1] 3,4,5,[5] 6,
}
for k, v in ipairs(tab) doprint(k .. : .. v)
end
输出
1:2
2:4
3:5
实际的table结构
local tab: {[0]: integer 1,[1]: integer 2,[-1]: integer 3,[2]: integer 4,[3]: integer 5,[5]: integer 6,
}可以看到0和负数都被ipairs自动略过了有意思的是由于[4]没有定义因此被认为是nil而停止了迭代。
总结ipairs会略过数组的0和负数索引以及其他字典索引从数组的[1]索引开始迭代(对应index0)顺序迭代直到某个索引不存在或其对应的值为空时结束 pairs()
让我们把上述几个例子用pairs遍历一下
local tab {23,35,[3] 45,78,[8] 101,nil,80
}for k,v in pairs(tab) doprint(k..:..v)
end
输出
1:23
2:35
3:78
5:80
8:101
table的结构是这样
local tab: {[1]: integer 23,[2]: integer 35,[3]: integer 45|78,[4]: nil,[5]: integer 80,[8]: integer 101,
}可以看到重复定义的元素值还是选择了后者并且nil被无视了
local tab {[b]8,[0] 1,2,[-1] 3,4,5,[5] 6,[a]7,
}
for k, v in pairs(tab) doprint(k .. : .. v)
end
输出
1:2
2:4
3:5
0:1
b:8
a:7
-1:3
5:6
实际的table结构
local tab: {[0]: integer 1,[1]: integer 2,[-1]: integer 3,[2]: integer 4,[3]: integer 5,[5]: integer 6,[a]: integer 7,[b]: integer 8,
}有意思的是pairs是先按数字顺序输出了数组然后碰到了不存在的索引[4]随后输出了0,b,a,-1。顺序十分诡异最后才输出了[5]。我不知道为什么这样输出但是这种输出方式也侧面证明了数组不要和字典一起定义
总结 ipairs会略过数组非正数索引以及其他字典索引从数组的[1]索引开始迭代(对应index0)顺序迭代直到某个索引不存在或其对应的值为空时结束。
pairs可以输出table内除了nil以外的所有元素。但是数组和字典的混合以及带有非正值数字索引的元素输出方式会很诡异。
所以别用非正数索引实际上非正索引应当称为自定义索引也别把数组和字典定义在一个table里 回到Table
table将key的值设为nil它的真实含义是删除掉这个key这和其他脚本很不一样也可能引发一些问题比如看下面例子
local t {1, 2, nil, 4}
print(#t) --- 4
for k, v in ipairs(t) do print(v) end --- 1 2
for k, v in pairs(t) do print(v) end --- 1 2 4
for i 1, #t do print(t[i]) end --- 1 2 nil 4可以看到使用迭代器是直接无视nil的但使用for遍历会得到nil我们本意是想删除这个元素但是它依然存在于table中 那么nil不等于删除吗请看下列的例子
local t {1, 2, nil, nil, 5}
print(#t) -- 5
t {[1]1, [2]2, [3]nil, [4]nil, [5]4}
print(#t) -- 2直接定义nil时nil是会计入table的长度的。但主动定义键值对时nil不会计入table的长度。因此当我们定义table时应当以键值对的方式定义
过分吗还有更过分的
a { [1] 1, [2] 2, [5] 5, [6] 6 }
print(#a) --2
b { [1] 1, [2] 2, [4] 4, [5] 5, [6] 6 }
print(#b) --6
c { [1] 1, [2] 2, [4] 4, [5] 5, [6] 6, [9] 9 }
print(#c) --6
d { [1] 1, [2] 2, [4] 4, [5] 5, [6] 6, [8] 8, [9] 9 }
print(#d) --6发现了吗键值对形式存储时中间如果隔了一个nil那么长度会接上如果隔了两个nil长度就会断开 ??? (O.o)