我正在处理perl中的哈希表。
我有多个字符串,具有多个长度和多个-
:
pre1-pre2-text1-text2
pre3-text3
pre4-pre5-pre6-text4
我有一个带有以下键的%hash
:
pre1-pre2
pre3
pre4-pre5-pre6
因此,键%hash
仅包含字符串的pre
部分。
如何确定第一个字符串pre1-pre2-text1-text2
和%hash
的键之间是否匹配?
答案 0 :(得分:2)
一种方法:使用键交替形成模式,并针对该模式测试字符串
use warnings;
use strict;
use feature 'say';
my @strings = qw(pre-not pre1-pre2-text1-text2 pre3-text3 pre4-pre5-pre6-text4);
my %h = ( 'pre1-pre2' => 1, 'pre3' => 1, 'pre4-pre5-pre6' => 1 );
my $keys_re = join '|', map { quotemeta } keys %h;
foreach my $str (@strings) {
say $str if $str =~ /$keys_re/;
}
这具有二次复杂度,但是交替不会遍历所有键,而是C(正则表达式本身)。
可能的改进(或必要性!)可能是对键进行适当排序。例如,最短的优先
my $keys_re = join '|', map { quotemeta } sort { length $a <=> length $b } keys %h;
如果某些键具有相同的部分,这可能会有所帮助,但请注意,这可能是一次不重要的调整,可能会影响正确性-并且可能需要 ;仔细考虑。
要获取密钥本身,请在模式周围添加捕获括号
foreach my $str (@strings) {
say "$str matched by key: $1" if $str =~ /($keys_re)/;
}
其中$1
包含与之匹配并被捕获的替代,这是关键。
答案 1 :(得分:1)
我在小Perl代码中添加了您提供的输入,并且可以检查按键是否匹配
#!/usr/bin/perl
use warnings;
my %langs = ( "pre1-pre2" => 'pre1-pre2',
"pre3" => 'pre3',
"pre4-pre5-pre6" => 'pre4-pre5-pre6');
@pats=("pre1-pre2-text1-text2", "pre3-text3", "pre4-pre5-pre6-text4");
for(keys %langs){
foreach $ss (@pats){
if (index($ss,$_) != -1){
print("Key contains:",$_, "|", $ss,"\n");
}
else{
print("NOT FOUND:",$_, "|", $ss,"\n");
}
}
}
注意:如果我正确地理解了您的要求,那么它将为您提供帮助。
答案 2 :(得分:1)
此答案假设pre
不能出现在字符串的中间(即,您不会有pre1-pre2-text1-pre5
这样的字符串,而前缀只会是pre1-pre2
)。如果此假设无效,请使用/^((?:pre\d+)(?:-pre\d+)*)/
代替/^(.*pre\d+)/
(我更喜欢后者,因为它可读性更好,但前者更为精确)。
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my %pre = map { $_ => 1 } qw(pre1-pre2 pre3 pre4-pre5-pre6);
while (<DATA>) {
my ($prefix) = /^(.*pre\d+)/;
if ($prefix && exists $pre{$prefix}) {
say "Prefix exists: $prefix";
} else {
say "Prefix doesn't exist: $prefix";
}
}
__DATA__
pre1-pre2-text1-text2
pre3-text3
pre4-pre5-pre6-text4
pre7-pre8-text5
如果您可以在行pre1-pre2-text1
中使用前缀应该只是pre1
,则此解决方案将不起作用。在这种情况下,除了迭代哈希的所有键并检查它们是否与字符串的开头匹配之外,您别无选择。
while (<DATA>) {
for my $prefix (keys %pre) {
if (/^\Q$prefix/) {
say "Found prefix: $prefix";
last;
}
}
}
但是,这要低得多,因为您需要遍历每一行的所有哈希键。
关于\Q
:即使您的前缀包含特殊的正则表达式字符(例如+
或.
),它也可以确保该解决方案有效。如果前缀始终像pre1-pre2
一样,则可以省略\Q
。
如果您在理解my %pre = map { $_ => 1 } qw(pre1-pre2 pre3 pre4-pre5-pre6);
时遇到困难:这是简明的版本
my %prev = (
'pre1-pre2' => 1,
'pre3' => 1,
'pre4-pre5-pre6' => 1
);