【发布时间】:2019-06-17 14:26:33
【问题描述】:
伙计们。有人可以帮我解决这个问题吗?
输入
a = {}
a.c = {1,2,3}
print(#a)
print(a.c)
输出
0
table: 0x11ed7a0
为什么#a 是0?为什么不是 1?
谢谢。
【问题讨论】:
伙计们。有人可以帮我解决这个问题吗?
输入
a = {}
a.c = {1,2,3}
print(#a)
print(a.c)
输出
0
table: 0x11ed7a0
为什么#a 是0?为什么不是 1?
谢谢。
【问题讨论】:
它为零,因为您的表 a 不是序列。
序列是使用 1..n 中的键的表,其中 n 是序列的大小。
换句话说,# 用于序列长度,而不是表长度。
只有一个边框的表格称为序列。例如,表 {10, 20, 30, 40, 50} 是一个序列,因为它只有一个边界 (5)。桌子 {10, 20, 30, nil, 50} 有两个边界(3 和 5),因此它不是 顺序。表格 {nil, 20, 30, nil, nil, 60, nil} 有三个边框(0, 3, 和 6),所以它也不是一个序列。表 {} 是一个边界为 0 的序列。 请注意,非自然键不会影响表是否为序列。
当 t 是一个序列时,#t 返回它唯一的边框,对应于 序列长度的直观概念。当 t 不是序列时,#t 可以返回其任何边界。 (具体取决于具体情况 表的内部表示,这又取决于表的方式 已填充并且其非数字键的内存地址。)
【讨论】:
Lua 表是一种不同于其他语言的结构。正如Lua manual 所说:
表是 Lua 中主要的(实际上是唯一的)数据结构机制,也是一种强大的机制。我们用表来表示普通的数组、符号表、集合、记录、队列等数据结构,简单、统一、高效。
此外,表格具有足够的动态性,您可以同时以多种方式使用它。例如,一个表可以同时用作数组和映射。这在内部会产生一些不幸的后果。在内部,每个 Lua 表都有两部分:数组和哈希映射。
长度运算符只对表的数组部分进行操作;没有额外的内存用于存储表中的项目总数,包括哈希映射部分。如果需要该功能,则必须手动实现。这样做的几个好方法是使用 getter 和 setter、手动更新本地计数器或使用带有 index 和 newindex 元方法的代理表。
作为一个有趣的旁注,有时很难判断一个值是存储在表的数组部分还是散列部分中。考虑 Lua 5.3 中的这些示例:
1: t = {true, nil, true} -- #t = 3
2: t = {true, [2] = true} -- #t = 2
3: t = {true, [3] = true} -- #t = 1
4: t = {true, true, true} t[2] = nil -- #t = 3
【讨论】:
t = {1, 2, nil, 4} t[5] = 5 创建了一个包含键 1、2、4 的 4 项数组部分和包含键 5 的单项哈希部分(我检查了最新版本的lua-getsize 来自 Github),但 #t 是 5 而不是 4。
t = {1, 2, nil, 4} 在内部创建了一个大小为 8 的数组,并用数字填充位置 1、2 和 3(内部表示为 0、1 和 2)。然后它向其中添加第五个元素,该元素也适合数组。这使得数组的大小为 5.
t = {true, true, true, true} t[8] = true 返回长度为 8。一些有趣的其他情况由于这种二分搜索,t = {true, true, true, true} t[6] = true --> 长度为 6,t = {true, true, true, true} t[7] = true --> 长度为 4。简而言之,稀疏数组的长度未定义。