Ruby可伸缩字符串匹配

时间:2014-08-21 03:54:46

标签: ruby string-matching dfa

我想非常快速地将字符串字典与模式字典进行匹配。

我有10000个长度为255的输入,以及10000个长度为20的模式。我需要非常快速地匹配这些字符串,我需要知道哪些模式匹配哪些输入。

我的模式需要支持正则表达式匹配。现在,我拥有一个mysql数据库中的所有内容,并且我在mysql中使用正则表达式调用来执行我需要的操作。例如:

patterns.each do |p|
  select * from inputs where inputs.value regex #{p}
end

但是我的模式越多,速度越慢越慢。我也考虑过:

patterns.each do |p|
  inputs.grep(p)
end

但是当我有太多的模式时,它会有同样的问题。我想在ruby中创建一个DFA并将其存储在内存中(单独的工作进程),直到需要它为止,但我不知道是否有任何资源可用于执行此类操作。

1 个答案:

答案 0 :(得分:3)

如果你不需要比赛,只需加入正则表达式;然后速度在C.概念证明:

# prepwork:
# make 676 two-letter patterns plus a digit
patterns = ('a'..'z').flat_map { |x| ('a'..'z').map { |y| x + y + "\\d" } }
# convert to regexp
regexp = Regexp.union(patterns.map{ |pattern| /(#{pattern})/ })

# matching:
# match
match = regexp.match("mu5")
# find out which pattern was hit
if match
  puts patterns[match.captures.find_index { |x| x }]
  # => mu\d
end

如果您需要查看哪个模式被击中,您可以使用任何捕获括号,或者您需要重写我的示例以使用命名捕获而不是普通模式,这不应该太难

编辑:如果您需要查看哪个模式被点击,您可以通过从正则表达式中删除括号来加快速度,将/(#{pattern})/替换为{{ 1}},这样匹配不需要每次都创建一个巨大的数组。