我需要抓取一组大小不确定的数据,并为其构建一个表键/值索引。由于我事先不知道维数,似乎我必须使用递归函数。我的Lua技能是非常新和肤浅的。我很难理解如何处理从函数调用返回表的问题。
注意:这是针对
Lua 5.1
脚本处理器
API = function(tbl)
local table_api = {}
-- do stuff here with target data and add to table_api
table_api["key"] = value
-- then later there is a need to recurse deeper into target data
table_api["lower"] = API(var)
return table_api
end
result = API(source_data)
在我所知道的大多数其他语言中,都有某种方法可以生成递归行
table_api["lower"] = API(var)
但由于Lua是通过引用来处理表变量的,所以我的返回子表一直被覆盖,我的结果只是应该的最后一点。
仅作为我的背景:
我正在使用一个商业应用程序,它的Lua脚本接口文档很少。它运行的是Lua5.1,API没有很好的文档记录,也没有经常更新。据我所知,所有内容都存储在G中,所以我想写一些东西来对API进行反向工程。我有一个可运行的递归函数(此处未显示),它枚举所有的返回值。对于该返回值,它只构建一个带注释的字符串,并逐步构建在该字符串上。这一切都很好,非常有用,但它显示了更多的API接口;所有实际的数据元素都包含在内,因此我必须筛选30000条记录,以确定一个包含大约500个术语的API集。为了确定API,我试图使用这个问题中讨论的子表返回值递归函数。我在这里展示的代码只是较大函数的一小部分。
我将继续并在这里包含完整的代码。我希望以增量方式构建一个包含每个API级别、任何子级别以及最终在最低级别使用的任何键的大型表。
最后,我希望有一个可以这样处理的表:
result["api"]["label"]["api"]["sublabel"]["value"]["valuename"]
完整代码:
tableAPIShow = function(tbl, table_track)
table_track = table_track or {}
local table_api = {}
if type(tbl) == 'table' then
-- Check if values are tables.
local parent_table_flag = true
for ind,val in pairs(tbl) do
if type(val) ~= 'table' then
parent_table_flag = false
break
end
end
-- If all children are table type, check each of them for subordinate commonality
local api_flag = false
if parent_table_flag == true then
local child_table = {}
local child_table_flag = false
api_flag = true
for ind,val in pairs(tbl) do
-- For each child table, store the names of the indexes.
for sub_ind,sub_val in pairs(val) do
if child_table_flag == false then -- First time though, create starting template view of typical child table.
child_table[sub_ind] = true -- Store the indexes as a template table.
elseif child_table[sub_ind] == nil then -- Otherwise, test this child table compared to the reference template.
api_flag = false
break
end
end
if api_flag == false then -- need to break out of nested loop
break
end
child_table_flag = true
end
end
if api_flag == true then
-- If everything gets to here, then this level is an API with matching child tables below.
for ind,val in pairs(tbl) do
if table_api["api"] == nil then
table_api["api"] = {}
end
table_api["api"][ind] = tableAPIShow(val, table_track)
end
else
-- This level is not an API level, determine how to process otherwise.
for ind,val in pairs(tbl) do
if type(val) == 'table' then
if table_track[val] ~= nil then -- Have we already recursed this table?
else
table_track[val] = true
if table_api["table"] == nil then
table_api["table"] = {}
end
table_api["table"][ind] = tableAPIShow(val, table_track)
end
else -- The children are not tables, they are values
if table_api["value"] == nil then
table_api["value"] = {}
end
table_api["value"][ind] = val
end
end
end
else
-- It's not a table, just return it.
-- Probably never use this portion because it's caught on upper level recurse and not called
return tbl
end
return table_api
end
我在主脚本中调用此函数,如下所示:
local str = tableAPIShow(_G)
我有另一个递归显示表的函数,这样我可以查看我的结果,看到我只得到一个返回值,它只包含顶级的值(我排除了内置的Lua函数/值,因为我只对应用程序API感兴趣):
{
[value] = table: 00000000F22CB700 {
[value][_VERSION] = Application/5.8.1 (x86_64; Windows NT 10.0.16299),
[value][tableAPIShow] = "function: 00000000F22C6DE0, defined in (121-231) C:\\Users\\user\\AppData\\Local\\Temp\\APP\\/~mis00002690 ",
[value][_FINAL_VERSION] = true,
[value][Path] = ./Scripts/Database/elements/,
[value][class] = "function: 00000000F1953C40, defined in (68-81) Scripts/Common/Class.lua ",
[value][db_path] = ./Scripts/Database/,
[value][merge_all_units] = "function: 00000000F20D20C8, defined in (2242-2250) Scripts/Database/db_merge.lua ",
}