Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns Lua-如果介于2个特殊字符之间,则使用string.find返回true_Design Patterns_Lua_Lua Patterns - Fatal编程技术网

Design patterns Lua-如果介于2个特殊字符之间,则使用string.find返回true

Design patterns Lua-如果介于2个特殊字符之间,则使用string.find返回true,design-patterns,lua,lua-patterns,Design Patterns,Lua,Lua Patterns,我需要一个模式,该模式将与string.find(或string.match,如果需要)一起工作,如果“表路径”字符串匹配,该模式将返回true。这是我的职责: local function FindValueFromPattern(myTable, pattern, previousPath) for key, value in pairs(myTable) do local path; if (not previousPath) then

我需要一个模式,该模式将与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..color”
其中
是“module”的任何子表,并且还有一个名为“color”的子表,因此向下遍历该表时,无论使用什么表,都将返回一个值(不必是外观表):

——还应打印“蓝色”(“设置”不应为必填项);
打印(FindValueFromPattern(待定,“模块..颜色”));
我可能需要更改逻辑,在表中插入找到的值,然后在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
对提供的键中的每个
键进行迭代

此函数可以更改为输出一个包含所有找到的
color
s的表,但当前仅返回一个值。返回的值是找到的
颜色
,如果找不到匹配项,则返回的值是
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
函数FindValueFromPattern(选项卡,键)
本地t_ref=tab
对于k-in键:gmatch(“%.*([^.]+)”)do
如果k==”并且类型(t_ref)==“table”,则
本地temp1
本地temp2
对于任何成对(t_ref)的
本地新密钥=密钥:gsub(k,任意)
temp1=FindValueFromPattern(制表符,新按键)
新密钥=密钥:gsub(k,任意...“)
temp2=FindValueFromPattern(制表符,新按键)
如果是temp1或temp2,那么
打破
结束
结束
t_ref=temp1或temp2
打破
其他的
如果t_ref==nil或type(t_ref)~=“table”,则
t_ref=零
打破
结束
t_ref=t_ref[k]
结束
结束
返回t_ref
结束
示例用法:

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
sample={
a={
b={
c={
color=“蓝色”,
},
roloc=1,
color=“红色”,
},
d={
e={
color=“紫色”,
},
roloc=“wolley”,
color=“黄色”,
},
}
}
colorFound=FindValueFromPattern(示例,“a..color”)
如果找到了,那么
打印(“已找到:…已找到颜色”)
其他的
打印(“未找到匹配项”)
结束
>>发现:红色

请记住,行为是不确定的,输出可能是
黄色
,而不是
红色
,并且在运行代码之前无法知道它将是哪个。

是否允许使用数字键?是否应该找到设置.module[3].color“
?@EgorSkriptunoff问得好。不,因为路径是人工创建的,我用
显式地连接每个键,所以如果pairs函数返回一个数字,例如,它看起来仍然像
“module.2.property”
,我可以在发送给函数的模式中使用它。谢谢询问。要匹配
“module..color”
字符串,您可以使用
“module%.[^.]+%.color”
模式。如果您需要提取任何部分,请使用捕获组将
[^.]+
包装起来:
“模块%。([^.]+)%.color”
@WiktorStribiżew谢谢,这看起来是一个很好的答案。对于我发布的解决方案,这不是必需的,但是使用
“模块%。([^.]+)%。([^.]+)%颜色”
也适用于这些键中有1个以上的情况吗?我以后可能需要这样做。关键是,
[^.]+
会匹配除
以外的任何连续字符一次或多次。我想是的。如果需要将字符限制为字母和数字,请使用
%w+
。如果需要匹配任何0个以上字符,请使用
-
(到第一个
.color
)或
+
(到最后一个
.color
)。
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