Regex 在没有循环的情况下获取字符串/正则表达式的Perl哈希键?

Regex 在没有循环的情况下获取字符串/正则表达式的Perl哈希键?,regex,perl,hash,Regex,Perl,Hash,我甚至不知道如何用一行字来表达这个问题,以下是我需要的: 我需要得到一个哈希键的元素,它是给定字符串的“子集”。所以如果我的哈希是 %h = ( 'ab' => 1, 'cd' => 2); 字符串是abc123,我会从散列中得到ab 我知道我能做到 $str = 'abc123'; foreach (keys %h) { print "$_ \n" if $str =~ m/^$_/; } 但我想问的是,是否有一种更有效的方法,比如,如果我像这样匹配另一种方法,它会起作

我甚至不知道如何用一行字来表达这个问题,以下是我需要的:

我需要得到一个哈希键的元素,它是给定字符串的“子集”。所以如果我的哈希是

%h = ( 'ab' => 1, 'cd' => 2);
字符串是
abc123
,我会从散列中得到
ab

我知道我能做到

$str = 'abc123';
foreach (keys %h) {
    print "$_ \n" if $str =~ m/^$_/;
}
但我想问的是,是否有一种更有效的方法,比如,如果我像这样匹配另一种方法,它会起作用

%h = ('abc123' => 1, 'def456' => 2);
print "$_ \n" for grep /^ab/, keys %h

简短的回答-不,不是真的。如果不检查每个子字符串,则无法找到匹配的子字符串。
for
map
并不能让你提高效率,它们在幕后暗中循环


但是,如果正则表达式是静态的,那么您可以通过提前编译正则表达式来获得一些效率

您可以将循环隐藏在对
grep
的调用中,如第二个示例所示

my %h = ( ab => 1, cd => 2 );
my $str = 'abc123';

print "$_\n" for grep { $str =~ /^$_/ } keys %h;
但速度优势可能很少或根本没有

如果您只想找到其中一个散列键,那么可以从中构建正则表达式,如下所示

my $re = join '|', sort { length($b) <=> length($a) } keys %h;
$re = qr/$re/;
print "$1\n" if $str =~ /^($re)/;

我认为map不会比for或foreach更快。事实上,一个快速的谷歌搜索显示它甚至可能更慢!这也是对映射的误用,因为您忽略了返回值
map
旨在通过对每个元素应用函数将一个列表转换为另一个列表map和foreach之间没有区别。内部实现也是一样的。map是perl做同样事情的另一种方式,它只是一个演示代码片段。它可能会返回匹配项的列表。我不清楚你在找什么。第二个示例与第一个示例相同,因为您选择的是散列键的子集。唯一不同的是,它看起来更简洁,因为您已将循环隐藏在
grep
call中。请查看我对第二个示例的编辑。第二部分很好,谢谢!是的,我只是在寻找一个匹配项。但是,我能问一下为什么排序吗?@mavili:排序是这样的,以便首先找到较长键的匹配项,因此在
ab
之前捕获
abc
实际上,for循环至少比键的连接和正则表达式的匹配快两倍!我很惊讶,但仅用几个键计时,我就可以分别得到5.698e-05ms和2.193e-05ms的答案和for循环。我想知道如果有大量的键,是否会有好处?@mavili:你应该只测试regex匹配语句。前两行中模式的构建和编译只需完成一次。是的,由于正则表达式引擎构造了一个trie来执行比较,因此使用更大的哈希值可能会获得更大的优势
print "$1\n" if $str =~ /^($re)/;