我需要将与string.find工作(或必要时string.match)将返回true,如果一个“表路径”字符串匹配的模式。这是我的功能:
local function FindValueFromPattern(myTable, pattern, previousPath)
for key, value in pairs(myTable) do
local path;
if (not previousPath) then
path = key;
else
path = string.format("%s.%s", previousPath, key);
end
if (path:find(pattern)) then
return value;
elseif (type(value) == "table") then
value = FindValueFromPattern(value, pattern, path);
if (value ~= nil) then
return value;
end
end
end
return nil;
end
local tbl = {}
tbl.settings = {};
tbl.settings.module = {};
tbl.settings.module.appearance = {};
tbl.settings.module.appearance.color = "blue";
print(FindValueFromPattern(tbl, "settings.module.appearance.color")); -- prints "blue";
上述工程的代码,但我想现在改变模式:
"module.<ANY>.color"
其中<ANY>
是“模块”的任何子表,也有所谓的“颜色”子表,所以向下遍历表的时候,一个值将不管使用什么表返回(不必是外观表) :
-- should also print "blue" ("setting." should not be required);
print(FindValueFromPattern(tbl, "module.<ANY>.color"));
而不是返回找到的值直线距离,我可能要改变逻辑插入在表中找到值,然后for循环后返回的表,但我写这篇很快来说明这个问题。
所以现在的问题是,将这种模式是什么样子?谢谢。
你在那里做什么是非常低效的。更好的方法是分裂在每个.
,只是索引表中的字符串。
一个简单的版本,不接受“任何”看起来是这样的
function findintable(tab, path)
local pos = path:find(".", 1, true)
if pos then
local tab = tab[path:sub(1, pos-1)]
if not type(tab) then error("Expected value to be table, got "..type(tab), 1) end
return findintable(tab, path:sub(pos+1, -1))
else
return tab[path]
end
end
添加的可能性为任意键(他......他......他......)会增加一些复杂性,需要一个循环,但它也是可行的
function findintable(tab, path)
local pos = path:find(".", 1, true)
if not pos then
return tab[path]
end
local key, rest = path:sub(1, pos-1), path:sub(pos+1, -1)
if key == "*" then
for k, v in pairs(tab) do
if type(v)~="table" then return end
local res = findintable(v, rest)
if res then return res end
end
return
else
local tab = tab[path:sub(1, pos-1)]
if not type(tab) then error("Expected value to be table, got "..type(tab), 1) end
return findintable(tab, path:sub(pos+1, -1))
end
end
这应该做你想要什么。只要改变任何你想要的占位符是“*”。
我用gmatch
与图案%.*([^.]+)
通过在所提供的密钥的每个key
进行迭代。
此功能可以改变输出找到的所有color
s的表,但目前只返回一个值。返回的值是发现color
或nil
如果没有找到匹配。
function FindValueFromPattern(tab, keys)
local t_ref = tab
for k in keys:gmatch("%.*([^.]+)") do
if k == "<ANY>" and type(t_ref) == "table" then
local temp1
local temp2
for any in pairs(t_ref) do
local new_keys = keys:gsub(k, any)
temp1 = FindValueFromPattern(tab, new_keys)
new_keys = keys:gsub(k, any .. ".<ANY>")
temp2 = FindValueFromPattern(tab, new_keys)
if temp1 or temp2 then
break
end
end
t_ref = temp1 or temp2
break
else
if t_ref == nil or type(t_ref) ~= "table" then
t_ref = nil
break
end
t_ref = t_ref[k]
end
end
return t_ref
end
使用示例:
sample = {
a = {
b = {
c = {
color = "blue",
},
roloc = 1,
color = "red",
},
d = {
e = {
color = "purple",
},
roloc = "wolley",
color = "yellow",
},
}
}
colorFound = FindValueFromPattern(sample, "a.<ANY>.color")
if colorFound then
print("Found: " .. colorFound )
else
print("No matches found")
end
>> Found: red
记住的行为是不确定的,它可以使输出为yellow
而不是red
,它无法知道它会直到代码运行。