“Transpose/Zip”函数未如预期工作。
2014-7-4 10:10:49
收藏:0
阅读:121
评论:2
我正在尝试使用 Lua 中的 mapn 和 zip 函数构建一个优雅的转置函数。
mapn 和 zip 的定义如下(来自《Lua 书》):
function map(func, array)
local new_array = {}
for i,v in ipairs(array) do
new_array[i] = func(v)
end
return new_array
end
function mapn(func, ...)
local new_array = {}
local i=1
local arg_length = table.getn(arg)
while true do
local arg_list = map(function(arr) return arr[i] end, arg)
if table.getn(arg_list) < arg_length then return new_array end
new_array[i] = func(unpack(arg_list))
i = i+1
end
end
这些函数的表现符合预期。
然后我定义了 zip 和 transpose 如下:
function zip(...)
return mapn(function(...) return {...} end,...)
end
function transpose(...)
return zip(unpack(...))
end
现在 transpose({{1,2},{3,4},{5,6}}) 可以像预期的那样生成 {{1,3,5},{2,4,6}}。
但是 transpose({{1,2},{3,4},{5}}) 不能生成 {{1,3,5},{2,4}},它只生成了一行。
我该如何使其生成我期望的结果?
我决定写一个“不太优雅”的函数。似乎没有很好的方法使用 mapn 等函数。
function transp(L)
local n=#L
local m,M=1e42,0
--Get the beginning and end of resultant transpose list.
for i=1,n do
for k,v in pairs(L[i]) do
if M<k then M=k end
if m>k then m=k end
end
end
local nt={}
for i=m,M do
local rt={}
for j=1,n do
rt[j]=L[j][i]
end
table.insert(nt,rt)
end
return nt
end
请批评和改进这个候选解决方案。
原文链接 https://stackoverflow.com/questions/8046009
点赞
stackoverflow用户12048
你示例中的 {5}
被忽略了,是因为这一行代码:
if table.getn(arg_list) < arg_length then return new_array end
你可能需要的是仅当 arg_list
为空时才跳出循环。
只有行长度单调递增时,这样做才能得到你想要的结果。
对于更一般的情况,当后面的行可能比前面的行更短时(例如{{1,2},{3,4,5},{6}}
),你需要跟踪行长度以允许填充缺口。可以通过向 map
添加可选参数(以及额外的返回值)来实现这一点,以指示在哪个最大下标 i
之前已评估 func(array[i])
:
function map(func, array, len)
local new_array = {}
len = len or #array
for i=1,len do
new_array[i] = func(array[i])
end
return new_array, len
end
function mapn(func, ...)
local new_array = {}
local i=1
local arg_length = select('#', ...)
local args = {...}
while true do
local arg_list, num_results = map(function(arr) return arr[i] end, args, arg_length)
if not next(arg_list) then return new_array end
new_array[i] = func(unpack(arg_list, 1, num_results))
i = i+1
end
end
function zip(...)
return mapn(function(...) return {...} end,...)
end
function transpose(...)
return zip(unpack(...))
end
2011-11-08 18:46:45
评论区的留言会收到邮件通知哦~
推荐文章
- 如何在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 模式将字符串(嵌套数组)转换为真正的数组?
function map(func, array) local new_array = {} for i, v in ipairs(array) do new_array[#new_array + 1] = func(v) end return new_array end
function mapn(func, ...) -- 使用可变长参数绑定到一个数组中。 local arrays = {...} local new_array = {} -- 简单的 for 循环。 local i = 1 while true do local arg_list = map(function(arr) return arr[i] end, arrays) if #arg_list == 0 then break end new_array[i] = func(unpack(arg_list)) i = i + 1 end return new_array end
-- 使用 'mapn' 替代 'map'(可能是你的本意)。 function zip(...) return mapn(function(...) return {...} end,...) end
-- 和之前一样的函数。 function transpose(...) return zip(unpack(...)) end
for _, row in pairs(transpose({{1,2},{3,4},{5}})) do for _, col in pairs(row) do io.write(col .. ' ') end io.write('\n') end -- 输出: 1 3 5 -- 2 4
```