我正在使用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现在转置({1,2},{3,4},{5,6}})产生{1,3,5},{2,4,6}。
但是转座子({1,2},{3,4},{5})不产生{1,3,5},{2,4}。它只产生一行。
我怎样才能得到我想要的结果呢?
我只是决定写一个“不雅”的函数代替。似乎没有顺利的方法使用地图和朋友。
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请评论并改进此候选解决方案。
发布于 2011-11-08 15:15:34
我在您的代码中修正了一些东西,我认为它现在按预期工作了,我已经在行中添加了注释。
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, ...)
-- Variadic arguments bound to an array.
local arrays = {...}
local new_array = {}
-- Simple for-loop.
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
-- Using 'mapn' instead of 'map' (probably how you intended).
function zip(...)
return mapn(function(...) return {...} end,...)
end
-- Same as before.
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
-- Output: 1 3 5
-- 2 4发布于 2011-11-08 18:46:45
您的示例中的{5}正被忽略,因为这一行:
if table.getn(arg_list) < arg_length then return new_array end相反,您可能要做的是,只有在arg_list为空时才能脱离循环。
这将给出您想要的结果,前提是行的长度是单调增长的。
在更一般的情况下,以后的行可能比前面的行短。
(例如,{{1,2},{3,4,5},{6}}),您将需要跟踪行的长度,以允许孔。这可以通过向map添加一个可选参数(和额外的返回值)来实现,以指示计算func(array[i])的最大索引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(...))
endhttps://stackoverflow.com/questions/8046009
复制相似问题