使用Lua匹配查找模式存在问题。

我正在为这个问题苦苦挣扎:

给定两个字符串:

s1 = '/foo/:bar/oof/:rab'
s2 = '/foo/lua/oof/rocks'

我想要得到以下信息:

  1. 它们是否匹配(这两个字符串应该匹配,s2 遵循了 s1 描述的模式)。

  2. 一个表格,其中存有 s2 中的值和相应的 s1 中的名称。在这种情况下,我们将得到:{ bar = "lua", rab = "rocks" }

我认为这个算法可以解决它,但我不知道如何实现它(可能需要使用 gmatch):

  1. 把占位符 : 的索引存储为一个表格的 KEY,并将相应的值作为这些占位符的名称。

    s1 为例:

    local aux1 = { "6" = "bar", "15" = "rab" }
    
  2. 通过获取 aux1 的键作为索引,将 s2 的值提取到另一个表格中:

    local aux2 = {"6" = "lua", "15" = "rocks"}
    
  3. 最后将它们合并为一个表格(这个很容易:P):

    { bar = "lua", rab = "rocks" }
    
点赞
用户3735873
用户3735873
function comp(a,b)
  local t = {}
  local i, len_a = 0
  for w in (a..'/'):gmatch('(.-)/') do
    i = i + 1
    if w:sub(1,1) == ':' then
      t[ -i ] = w:sub(2)
    else
      t[ i ] = w
    end
  end
  len_a = i
  i = 0
  local ans = {}
  for w in (b..'/'):gmatch('(.-)/') do
    i = i + 1
    if t[ i ] and t[ i ] ~= w then
      return {}
    elseif t[ -i ] then
      ans[ t[ -i ] ] = w
    end
  end
  if len_a ~= i then return {} end
  return ans
end

s1 = '/foo/:bar/oof/:rab'
s2 = '/foo/lua/oof/rocks'

for k,v in pairs(comp(s1,s2)) do print(k,v) end

将上述 Lua 代码翻译为中文并保留原本的 markdown 格式:

function comp(a, b)
  local t = {} -- 存储模式串中的占位符
  local i, len_a = 0 -- i 为序号,len_a 为模式串中的元素数量
  for w in (a..'/'):gmatch('(.-)/') do -- 以 '/' 为分隔符分割模式串
    i = i + 1 -- 序号增加
    if w:sub(1,1) == ':' then -- 如果是以 ':' 开头,说明这是一个占位符
      t[ -i ] = w:sub(2) -- 将占位符存入 t 中
    else -- 否则,说明这是一个元素
      t[ i ] = w -- 将元素存入 t 中
    end
  end
  len_a = i -- 记录模式串中的元素数量
  i = 0 -- i 重置为 0
  local ans = {} -- 存储结果
  for w in (b..'/'):gmatch('(.-)/') do -- 以 '/' 为分隔符分割目标串
    i = i + 1 -- 序号增加
    if t[ i ] and t[ i ] ~= w then -- 如果 t 中存在占位符且当前元素与占位符不相等,返回空表
      return {}
    elseif t[ -i ] then -- 如果 t 中存在占位符(注意这里使用了负数的序号)
      ans[ t[ -i ] ] = w -- 将占位符和对应元素存入结果表中
    end
  end
  if len_a ~= i then return {} end -- 如果模式串中元素数量不等于目标串中元素数量,返回空表
  return ans -- 返回结果表
end

s1 = '/foo/:bar/oof/:rab' -- 模式串
s2 = '/foo/lua/oof/rocks' -- 目标串

for k,v in pairs(comp(s1,s2)) do print(k,v) end -- 输出结果
2015-03-01 15:56:30
用户2239760
用户2239760

另一个解决方案可能是:

s1 = '/foo/:bar/oof/:rab'
s2 = '/foo/lua/oof/rocks'
pattern = "/([^/]+)"

function getStrngTable(_strng,_pattern)
    local t = {}
    for val in string.gmatch(_strng,_pattern) do
        table.insert(t,val)
    end
    return t
end
local r = {}
t1 = getStrngTable(s1,pattern)
t2 = getStrngTable(s2,pattern)
for k = 1,#t1 do
    if (t1[k] == t2[k]) then
        r[t1[k + 1]:match(":(.+)")] = t2[k + 1]
    end
end

r 将拥有所需的结果

以下解决方案更为整洁,也会给出相同的结果:

s1 = '/foo/:bar/oof/:rab'
s2 = '/foo/lua/oof/rocks'
pattern = "/:?([^/]+)"

function getStrng(_strng,_pattern)
    local t = {}
    for val in string.gmatch(_strng,_pattern) do
        table.insert(t,val)
    end
    return t
end
local r = {}
t1 = getStrng(s1,pattern)
t2 = getStrng(s2,pattern)

for k = 1,#t1 do
    if (t1[k] == t2[k]) then
        r[t1[k + 1]] = t2[k + 1]
    end
end
2016-03-15 22:18:11