Lua 表取长度

稀疏数组的长度返回的不对,不知道算不算是个 bug?(在 Lua5.2.2 中测试的)
如果一个表容量一半的元素,用 ‘#‘ 取长度取的不对。但是对于小于容量一半的情况,表现的是对的。
根据 Lua 的代码实现,‘#’号取表长度时取得是表中第一个空元素前的那个位置。
原文是(luaH_getn 注释) :
Try to find a boundary in table `t‘. A `boundary‘ is an integer index such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).

看下例子:

a = {}
for i = 1, 2 do
    a[i] = i*3
end
a[4] = 811

用 #a 取得的结果是 4,而根据上面的描述应该取回 2。

再如:

for i = 1, 4 do
    a[i] = i*3
end
a[8] = 811

用 #a 取得的结果是 8,而根据上面的描述应该取回 4。
在老一点的版本里可以用 table.maxn 取最大下标,新版本里这个接口被废除了。
简单的分析下原因,当表中的元素很少而下标的跨度很大时,也就是对于很稀疏的数组,存储的时候存在表的哈希部分。但当数组不是那么稀疏的时候,就存在了数组部分,就是按下标从 1 递增而来。这也是对空间使用的一种优化。
看下取长度的实现(只截取对分析有用的部分)

unsigned int j = t->sizearray;
if (j > 0 && ttisnil(&t->array[j - 1])) {
  // some codes
}
/* else must find a boundary in hash part */
else if (isdummy(t->node)) /* hash part is empty? */
  return j; /* that is easy... */
//some other codes

注意 if 里后面的那个表最后的一个元素判空操作,此时对于上面的两段代码 a[4] 或 a[8],刚好它们位于数组的最后一个元素,所以不是空,if 里面不执行。由于这里的表没有哈希部分,所以,到 else if 里直接返回表长,也就是上面看到的 4 或 8。

不过,实际中,对于稀疏数组不要用 ‘#‘ 取长度,因为这个操作没有什么意义。

Lua 表取长度

时间: 2024-10-15 14:58:12

Lua 表取长度的相关文章

Lua table 的长度问题

直入主题 我们要取lua table的长度时习惯这样 local tb = {1,2,3,4} print(#tb) 这时候,输出理所当然的是4,如果在程序中我们需要判断长度时使用这样的方法,再看一下 tb[1] = nil print(#tb) 输出还是4,似乎有点背离我们的意愿 我们想知道这个table里面是不是有4个值,但是有一个值被置空了,输出结果却没有及时告诉我们 发生这样问题的原因是,lua在初始化table的时候,会给这个table分配值存储的空间,代码里面tb初始化包含4个数字值

数据结构29:广义表的长度和深度

广义表的长度 通过前一节对广义表的介绍,例子中给出了几个广义表的长度.例如:空表的长度为 0,只含有一个原子的广义表长度为 1,等等. 广义表的长度指的是广义表中数据元素的数量.这里需要指明的是,一个广义表中,一个原子算做是一个元素,一个子表也只算做一个元素. 在 LS = (a1,a2,…,an) 中,ai表示原子或者子表, LS 的长度为 n. 广义表的深度 广义表的深度,指的是广义表中括号的重数.例如:C=(a,(b,c,d)): 图1 广义表C的深度 图1中,从前往后数左括号的数量就是广

LUA表克隆方法归纳

lua表克隆 将lua一个表, 克隆出一份为一个独立的另外一个表. 对于一个module, 如果在require之后,获得的表对象, 不能直接修改, 例如lua缓存此表, 但是多次逻辑执行, 都使用的是原始module, 这种情况就需要使用clone. clone实例, 例如将 {1} 克隆出一份 {1}, 使用 tostring 打印两个表,可以看到地址不同. 支持浅.深拷贝方法 深拷贝, 即当遇到表的key或者value也是表的时候, 将表也拷贝一份, 否则不拷贝, 否则的方法为浅拷贝. 对

字符串s中从第i个位置起取长度为len的子串,函数返回子串链表

/*已知字符串采用带结点的链式存储结构(详见linksrting.h文件),请编写函数linkstring substring(linkstring s,int i,int len),在字符串s中从第i个位置起取长度为len的子串,函数返回子串链表.*/ #include "linkstring.h"/*请将本函数补充完整,并进行测试*/linkstring substring(linkstring s, int i, int len){linkstring temp;int j;fo

HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵快速幂)

HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵快速幂) ACM 题目地址:HDU 3117 Fibonacci Numbers 题意: 求第n个斐波那契数的前四位和后四位. 不足8位直接输出. 分析: 前四位有另外一题HDU 1568,用取对的方法来做的. 后四位可以用矩阵快速幂,MOD设成10000就行了. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * Blog: http://blog.csdn.

游戏资源自动转换成Lua表

关于这个问题,几年前已经做过一个工具,自动导出成一个c++的struct,然后用vector存储这些数据,然而在实践中发现在遇到多层嵌套时,这种数据表现是非常乏力的.比如掉落表会配多个掉落物,每个掉落物都有数量.概率等.那么最好是将物品ID,数量,概率设置为一个struct然后用一个vector存储,而不是用drop_id1, drop_id2, drop_num1,drop_num2来表示,类似这样的情况是很常见的.后来工作中用Lua比较多,也曾写过一个将表导出lua的工具,对上述问题的解决方

mysql 多表查询等值连接、为表取别名

#案例:查询女神名和对应的男神名 SELECT NAME,boyName FROM boys,beauty WHERE beauty.boyfriend_id=boys.id; USE myemployees; #案例:查询employees表的员工名和对应的departments表的部门名,限定字段名相同 SELECT last_name,department_name FROM departments,employees WHERE employees.department_id=depar

为什么Java的hash表的长度一直是2的指数次幂?为什么这个(hash&amp;(h-1)=hash%h)位运算公式等价于取余运算?

1.什么是hash表? 答:简单回答散列表,运算在hash结构散列(分散)存放. 2.如何散列排布,如果均匀排布? 答:取余运算 3.Java中如何实现? 答:hash&(h-1) 4.为什么hash&(h-1)=等价于hash%h java的h(表长)一定是2的指数次幂,2的指数次幂2n 2n的结果:一定长这样10000...(n个0) 2n-1的结果:一定这样1111(n-1)个1 举个例子: 当h=16,对应的二进制:00010000 h-1=15,对应的二进制:00001111 可

Lua与C++ 第四篇(获取Lua表结构数据)

本文转载于:http://blog.csdn.net/musicvs/article/details/8445079 笨木头花心贡献,啥?花心?不呢,是用心~ 正文: 1. 什么是table table是Lua里最强大的数据类型,我们可以当成是数组,但是它又和数组有点不一样,建议大家看看Lua的语法教程,因为我对table也没有熟悉到可以给大家解释的程度. (旁白:那你还写什么教程...) 2. 获取table变量 现在,我们给helloLua.lua文件添加一个table全局变量: -- he