【问题标题】:How to match efficiently against keys in a table in Lua?如何有效地匹配 Lua 表中的键?
【发布时间】:2017-06-04 08:23:37
【问题描述】:

在我的 Lua 5.1 环境中可用的显然是默认的 Lua 模式匹配,但也是相当新的 PCRE 和 LPEG 版本。老实说,我不在乎使用哪一个。只要我的问题得到有效解决,我就很高兴。 (尤其是我个人对 LPEG 的了解几乎不存在,但我听说它有一些非常好的品质。)

我有一个表,其中包含某些字符串模式作为键,一旦键匹配,将使用随附的值......这意味着它们对于这个问题并不重要。

假设你有:

tbl = { ["aaa"] = 12, ["aab"] = 452, ["aba"] = -2 }

现在我的目标是找出其中哪一个首先在特定字符串中匹配,例如"accaccaacaadacaabacdaaba"

实际上,键更多,匹配字符串更长。这意味着简单地逐个匹配所有键并比较匹配开始的列是一种非常低效的解决方案,对我来说不可行。

部分匹配字符串也可能有相当多的重叠。从理论上讲,我知道每个键模式一个状态机在这方面是理想的;只需完成每个模式的动作,当你完全匹配其中一个模式时,你就完成了。

但是当我的环境中有如此多的模式匹配库时,我自己编写类似的代码会很疯狂。我知道的唯一一个技术能力是 PCRE;只需附加 "aaa|aab|aba" 之类的键,您将获得第一个可行的匹配项。

但也有问题。一方面,我不确定在编译这样的匹配时它有多智能。 (我认为它首先尝试'aaa',一旦失败就完全放松,然后完全尝试aab,但我还没有测试过)与匹配它相比效率不会太高,比如"a(a[ab]|ba)",相似性得到更快的解决。

此外,我希望能够提供一些灵活性(“a.ad”,其中第二个字符无关紧要,或者匹配一个数字......基本的东西)。以这种加法的方式使用类似的模式,我看不到有办法重新获得匹配的原始模式,因此我可以使用它的值。

(最坏的情况,我可以在表中生成很多条目来匹配每个可能的通配符变体并取消模式要求,但老实说我不想这样做。)

哪个库是完成这项工作的正确工具,如何才能最好地使用该库来实现上述目标,而无需重新发明轮子?

【问题讨论】:

  • 自己实现 Aho–Corasick 算法即可。
  • 有一个我不知道的算法。我会看看它。也就是说,我很惊讶像 PCRE 这样的流行库没有内置该算法的实现......

标签: lua pattern-matching pcre lpeg


【解决方案1】:

对您的问题的评论提到了 Aho–Corasick 算法。

如果您的环境可以访问os.executeio.popen,您可以调用fgrep -o -f patterns filename,其中patterns 是包含用换行符分隔的模式的文件的名称,而filename 是您的输入的名称。 -o 表示只输出匹配项,每行一个。您可以将filename 替换为-,以便fgrep 从标准输入中读取:echo "String to match" | fgrep -o -f patterns

fgrep 实现 Aho–Corasick 算法。

但是,请记住 Aho–Corasick 算法不能识别元字符。

【讨论】:

    【解决方案2】:

    正如 Alexander Mashin 的回答所说,Aho-Corasick 算法是一种有效的算法,可以解决您的问题。在 Lua 领域,cloudflare / lua-aho-corasick 是使用 FFI 的 LuaJIT 实现。还有一个纯 lua 实现 jgrahamc/aho-corasick-lua 可能会更慢。

    【讨论】:

      猜你喜欢
      • 2022-07-06
      • 1970-01-01
      • 2016-05-06
      • 2019-12-04
      • 2010-11-18
      • 2020-09-06
      • 2012-12-02
      • 2012-05-23
      • 2014-05-19
      相关资源
      最近更新 更多