如何在Lua中获取数组的尾部而不复制它?
我正在使用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
例如:
prompt> table.concat(tail({10, 23, 8}), ", ")
23, 8
但是,这是通过返回表的新副本实现的。有没有办法避免创建新表格?
我正在寻找等价于C的返回指向下一个元素的指针( t++)。这是可能的吗?
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)
如已经解释过的那样,通常这是不可能实现的。
但是,使用元表,您可以实现一个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
prapin的建议是使用元表来呈现序列的视图,这大致是我会做的方式。一个可能有用的抽象是为_segments_定义一个元表,它可以是一个0元函数,返回一个表和一个偏移索引的对 - 我们只使用函数来表示元组。然后我们可以定义一个元表,使得这个函数像一个表一样行为:
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元函数)以获取它们的内容。但如果您可能有兴趣扩展功能,比如对序列有更一般的视图,我认为这是更灵活的。
这是我知道的实现tail()的最好方法。它会创建一个新表,但我认为这是不可避免的。
function tail(list)
return {select(2, unpack(list))}
end
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
不行。你唯一可能想要这个功能的原因是出于性能考虑。这种特性只存在于低级编程语言中。Lua 是一种脚本语言:性能并不是如此重要,因此不会实现这个功能。
只需像你正在做的那样创建另一个表,或使用
table.remove来修改原始表。哪个对你最好就用哪个。记住:大而重要的对象,如表和用户数据,都是通过引用存储在 Lua 中的,而不是通过值。