Lua table 疑问

2022-02-07 17:13:56 +08:00
 pkwenda

给列表删除第二元素

aaa = {10,20,"30",nil,nil}
aaa[2] = nil
print(#aaa)
print(table.unpack(aaa))

输出:

1
10

给字符串 "30" 搞没了

为啥不是

3
10, nil,"30" 

后面两个 nil 删除就没事:

aaa = {10,20,"30"}
aaa[2] = nil
print(#aaa)
print(table.unpack(aaa))

3
10      nil     30

求教

1510 次点击
所在节点    程序员
6 条回复
mywaiting
2022-02-07 17:26:06 +08:00
关键字 nil as an element in a Lua table 搜索看看~
rrfeng
2022-02-07 17:36:07 +08:00
因为 table 作为 array (只有 value 没有 key )的时候,遍历遇到 nil 就会终止。
pkwenda
2022-02-07 17:47:39 +08:00
@mywaiting 查了木有查到才来问的 :<
@rrfeng 不是的看我最后的例子删除后面的两个 nil 正常输出,并没有终止


查了一圈,总结如下:
table 中有 nil 值时,#table 的结果并不确定

再引用一下 Lua 程序设计第四版原话:

> 可以将以 nil 结尾的列表当做一种非常特殊的情况
rrfeng
2022-02-07 19:11:36 +08:00
@pkwenda 嗯我记错了。
muzuiget
2022-02-07 19:11:54 +08:00
table 在本质就是一个字典结构,只不过可以使用数字类型做 key 而已,当 key 是数字类型时,Lua 在内部会做一些骚操作优化。

只要你将存值和取值分开看好理解了,例如

aaa = {}
aaa[1000] = 1234

并不会把 aaa 变成一个 1000 个长度的“数组”(别的语言可能叫“稀疏数组”)。

所以当你 aaa[2] = nil 时,这就不是一般意义上的数组了,Lua 在 C 结构上可能被优化掉了,# 操作符结果就是未定义了(顶多在告诉你在 C 层面用了多少内存)。

这表示你用

aaa = {10,20,"30"}

还是

aaa = {10,20,"30",nil,nil}

在 Lua 层面上是一样的,但是在 C 层面上,第二种写法,可以提示 Lua 这个 table 可以提前分配多少内存。
nightwitch
2022-02-07 22:57:33 +08:00
虽然同样是 table 这个数据结构,但是写的时候大脑里要严格区分序列,数组和哈希表三个概念。
PIL 4th 第四版的 5.3 节里量良定义了序列: 所有元素都不为 nil 的数组。

#作为取*序列*长度操作符,对于含 nil 元素的元表使用结果是未定义的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/832278

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX