0

我有看起来像这样的大单词列表(此数据来自 db):

[
    {
        keyword => 'bmw.*red.*1999',
        owner => 'someone'
        #... other attributes
    },
    {
        keyword => 'toyota.*black.*1999',
        owner => 'someone else'
        #... other attributes
    },
    # and so on ... up to 300 different keywords in a list
]

我必须定期将“关键字”与许多其他列表进行匹配。因为每次我将“关键字”编译为正则表达式时都会使用此关键字列表:

map { $_->{_compiled} = qr/$_->{keyword}/i } @keywords;

并将每个关键字与其他列表中的每个元素进行比较:

foreach my $other in (@other) {
    foreach my $keword (@keywords) {
        if ($other->{name} =~ $keyword->{_compiled}) {
              ## do something with $other and $keyword
        }
    }
}

这些操作应该每 10 分钟运行一次,并且应该有大约 50 个关键字列表(最多 300 个元素)和 50 个根据这些关键字检查的其他列表。它应该增长。

我想尽可能优化匹配速度,我有两个想法/问题:

  • 将编译的正则表达式($keyword->{_compiled})保存在数据库中以供以后使用,但我不确定这有多大帮助(我没有做任何基准测试)

  • 将所有“关键字”或“_compiled”加入一个大的正则表达式,并一步比较所有内容。

代码:

my @compiled = grep { $_->{_compiled} } @keywords;

# or is this better?
my $rx = "(".(join "|", grep { $_->{keyword} } @keywords).")";
my $compiled = qr/$rx/i;

foreach my $other in (@other) {
   if ($other->{name} =~ @compiled) {
       ## do something with $other and $keyword
       ## 
       ## but now there is no way to get "owner" of matched keyword

   }
}

我的“问题”是我必须能够使用匹配关键字的“所有者”和其他属性。如果我在一个大的正则表达式中加入所有内容或将 _compiled 放入一个数组中,我将无法匹配

是否有“最佳解决方案”将大列表与大列表进行正则表达式比较?我什至不确定我是否应该担心性能问题,但列表会增加,我想做好准备。

4

1 回答 1

1

您可以尝试将 : 更改bmw.*red.*1999

\bbmw\b(?>[^r]++|\Br|r(?!ed))++\bred\b(?>[^1]++|\B1|1(?!999))++\b1999\b

所有关键字都一样。此更改的目标是尽可能快地失败。

请注意,转换可以通过 2 次连续搜索/替换自动进行(始终相同)

search: (\w+)
replace: \b$1\b

search: \.\*(?=\\b(\w)(\w+)\\b)
replace: (?>[^$1]++|\B$1|$1(?!$2\b))++

带有第二个关键字的示例

toyota.*black.*1999
first replace:
\btoyota\b.*\bblack\b.*\b1999\b
second replace:
\btoyota\b(?>[^b]++|\Bb|b(?!lack\b))++\bblack\b(?>[^1]++|\B1|1(?!999\b))++\b1999\b

然后将编译后的表达式存储在数据库中。

于 2013-08-18T13:16:26.500 回答