我正在使用Lua 5.2,并且为了这个问题,假设这些表专门用作数组。
这是一个返回数组 tail 的函数(数组减去第一个元素):
function tail(t)
if # t <= 1 then
return nil
end
local newtable = {}
for i, v in ipairs(t) do
if i > 1 then
table.insert(newtable, v)
end
end
return newtable
end
例如:
提示&GT; table.concat(tail({10,23,8}),“,”)
23,8
然而,这是通过返回表的新副本来实现的。有没有办法避免创建新表?
我正在寻找等效的C返回指向下一个元素(t++
)的指针。有可能吗?
答案 0 :(得分:9)
如前所述,这通常是不可能的。
但是,使用元表,你可以实现一个tail
函数,通过引用原始表来执行你想要的而不复制所有数据。以下适用于Lua 5.2中的大多数操作,但不适用于table.concat
:
function tail(t)
return setmetatable({}, {
__index = function(_, k) return t[k+1] end,
__newindex = function(_, k, v) t[k+1] = v end,
__len = function(_) return #t-1 end,
__ipairs = function(_) return
function(_, i)
if i+1==#t then return nil end
return i+1, t[i+2] end,
t, 0 end,
__pairs = function(t) return ipairs(t) end,
})
end
答案 1 :(得分:4)
这是我知道实现tail()的最好方法。它创建了一个新表,但我认为这是不可避免的。
function tail(list)
return { select(2, unpack(list)) }
end
答案 2 :(得分:2)
我正在寻找等效的C返回指向下一个元素的指针(t ++)。有可能吗?
没有。您可能想要的唯一可能的原因是性能。这种功能只能在低级编程语言中找到。 Lua是一种脚本语言:性能不是优先考虑的事情。
只需制作您正在做的另一张桌子,或使用table.remove
修改原件。哪个最适合你。请记住:像表和userdata这样的重要大对象都是通过引用存储在Lua中,而不是按值存储。
答案 3 :(得分:2)
Nicol是正确的,你不能引用一个数组的片段,但有一个更容易/更短的方法来做你想做的事情:
function tail(t)
local function helper(head, ...) return #{...} > 0 and {...} or nil end
return helper((table.unpack or unpack)(t))
end
然后 print(table.concat(tail({10, 23, 8}), ", "))
将打印23,8
。
(添加table.unpack or unpack
使其也适用于Lua 5.2)
答案 4 :(得分:1)
do
local tail_mt = {
__index = function(f, k) local t, i=f(); return t[k+i] end,
__newindex = function(f, k, v) local t,i=f(); t[k+1] = v end,
__len = function(f) local t,i=f(); return #t-i end,
__ipairs = function(f)
local t,i = f ()
return
function (_, j)
if i+j>=#t then
return nil
else
return j+1, t[i+j+1]
end
end, nil, 0
end,
}
tail_mt.__pairs = tail_mt.__ipairs -- prapin collapsed this functionality, so I do too
function tail (t)
if type(t) == "table" then
return setmetatable ( function () return t, 1 end, tail_mt )
elseif type(t) == "function" then
local t1, i = t ()
return setmetatable ( function () return t1, i+1 end, tail_mt )
end
end
end
使用__index和__newindex元方法,您可以编写诸如f [2] = f [1] +1之类的代码。
虽然这个(未经测试的)代码不会无休止地创建一次性元表,但它可能不如prapin的效率高,因为它会调用thunks(0-ary函数)来获取它们的内容。但是如果您可能对扩展功能感兴趣,比如对序列有更多的一般看法,我认为这样会更灵活。