前言
因为一些神秘原因(指玩的游戏做mod需要lua),我决定把它学了
这里不会记录一些语法之类的可以从网上找到的教程内容,只会记录那些教程不讲,咱自己摸索出的东西
table中有nil会发生什么
教程当中讲,对于一个lua表
local array = {1, nil, 2}print(#array)输出结果应该是3
但是咱在实操当中结果是2
AI的回答是在lua表中添加nil会导致#运算符和ipair的结果不可预测
lua把#table定义为table的第一个border(t[i]返回nil)
但是问题在于,对于我们给出的array,t[2](赋值为nil)和t[4](超出表边界,不存在)的返回值都是nil
所以#array在寻找border时,既可能找到2,也可能找到4
比如对于下面这行代码
local array = {5, nil, "红酱自动机", 6, 7, 8}print(#array)输出结果就是6而不是2
所以实践当中最好不要在lua表里面加nil
pair, ipair的区别以及pair的一些特性
对于下面这段代码
do local table = { [false] = "false", [true] = "true", [1] = "one", [2] = "two", [3] = "three", name = "张三", age = 18, friend = { name = "李四", age = 20 } } for k, v in pairs(table) do print(k, v) end print("-------------") for k, v in ipairs(table) do print(k, v) end print("-------------") print(#table) -- 3end其输出为
false falsetrue true2 two3 threename 张三friend table: 0000000000fba550age 181 one-------------1 one2 two3 three-------------3lua的table被分为数组区和哈希区
ipair只遍历数组区,而pair把数组区和哈希区一起遍历
我们可以看到
[1] = "one",[2] = "two",[3] = "three",这些是被存在数组区的
那我们不禁要问了
int luaH_next (lua_State *L, Table *t, StkId key) { unsigned int asize = t->asize; unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */ for (; i < asize; i++) { /* try first array part(数组区遍历) */ lu_byte tag = *getArrTag(t, i); if (!tagisempty(tag)) { /* a non-empty entry? */ setivalue(s2v(key), cast_int(i) + 1); farr2val(t, i, tag, s2v(key + 1)); return 1; } } for (i -= asize; i < sizenode(t); i++) { /* hash part(哈希区遍历) */ if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */ Node *n = gnode(t, i); getnodekey(L, s2v(key), n); setobj2s(L, key + 1, gval(n)); return 1; } } return 0; /* no more elements */}源码里面写的是先顺序遍历数组区,再顺序遍历哈希区啊,怎么用pair进行遍历的时候,数组区的元素也没有按顺序输出呢?
答案是数组区是一个会随着插入元素数量变化的变长数组,而pair不保证后加入的数据一定在数组区
/*** Insert a key in a table where there is space for that key, the** key is valid, and the value is not nil.*/static void newcheckedkey (Table *t, const TValue *key, TValue *value) { unsigned i = keyinarray(t, key); if (i > 0) /* is key in the array part? */ obj2arr(t, i - 1, value); /* set value in the array */ else { int done = insertkey(t, key, value); /* insert key in the hash part */ lua_assert(done); /* it cannot fail */ cast(void, done); /* to avoid warnings */ }}插入的源码是这么写的www
如果keyinarray(一个用来检测key是否在数组区范围内的宏)告诉我们新元素的范围还在数组区内,就将其插入数组区,否则将其插入哈希区
那么如何让pair按顺序遍历呢(不建议这么做,因为插入新元素的时候会rehash,不保证新元素一定在数组区,会发生问题)?
将table按照默认方式初始化就行
do local table = { "one", "two", "three", [false] = "false", [true] = "true", name = "张三", age = 18, friend = { name = "李四", age = 20 } } for k, v in pairs(table) do print(k, v) end print("-------------") for k, v in ipairs(table) do print(k, v) end print("-------------") print(#table) -- 3end输出为
1 one2 two3 threefalse falsetrue trueage 18name 张三friend table: 0000000000eca1d0-------------1 one2 two3 three-------------3两相对比,我们还可以得到另外一个结论,lua表中非默认元素是在数组区初始化完成后再加入表的
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时






