在table中,nil不可以作为key,否则会有运行报错;而且,有时候使用#获取长度时,会因为nil而导致无法获取到正确的长度;如下,有一个函数,它是用来把参数进行反序,使用#获取长度,但是长度出现了问题;
function reverse(...)
local t = {...}
for i = 1,#t/2 do
local j = #t - i + 1
t[i],t[j] = t[j],t[i] -- swap
end
return table.unpack(t)
end
print(reverse(10, 20, 30))
print(reverse(10, nil, 30, nil))
print(nil, 30, nil, 10)
print(table.unpack({30, nil, 10, nil}))
解决方案:可以使用一个显式的'n'字段,如下,不是直接用...创建一个表,而是另外存储一个长度字段:
function reverse(...)
local t = { n = select('#', ...), ...}
for i = 1, t.n / 2 do
local j = t.n - i + 1
t[i], t[j] = t[j], t[i]
end
return table.unpack(t, 1, t.n)
end
print(reverse(10, 20, 30))
print(reverse(10, nil, 30, nil))
使用nil占位符
在一些特殊的例子中,我们需要使用nil作为key,可以使用如下的替代方案,封装一层接口,将nil作为参数传入,如果为nil,则使用另一个NIL来代替并进行索引;
do
local NIL = {}
function set_create(...)
local t = {}
for n = 1, select('#', ...) do
local v = select(n, ...)
t[v == nil and NIL or v] = true
end
return t
end
function set_exists(t, v)
return t[v == nil and NIL or v]
end
end
local t = set_create(10, nil, false)
assert(set_exists(t, 10))
assert(set_exists(t, nil))
assert(set_exists(t, false))
assert(set_exists(t, 'xx'))