perl中哈希键的字符串比较

时间:2015-10-27 16:38:01

标签: regex perl hash

我在perl中有一个哈希映射,如下所示:

MAP_MESSAGE_TO_NUMBER => {
     'Hello World, I am XYZ'    => 11,
     'I am using Stack Overflow for Guidance'   => 12,
     'Programming is good!' => 13,
},

在我的Perl代码中我试图与哈希键匹配,如果匹配发生,我只返回相应的哈希值(数字)。

我的代码工作正常。

my $Strtomatch = 'Hello World, I am XYZ!';
if ( some condition ) {
    my $val =   MAP_MESSAGE_TO_NUMBER->{$Strtomatch};
    # some code will use the return value 
    doSomethingWith $val;  
}

我的问题是:   如果您将看到变量$ Strtomatch的值有一个额外的字符'!'这在原始哈希映射中不存在。因此,我的哈希映射不会返回任何值。

我的问题是如何使这更通用,以便即使部分字符串匹配,我也可以进行比较。

即使很少的字符匹配其罚款也会返回值。

让我知道。

我不确定如何在这里使用正则表达式,因为我正在使用来自其他函数的值来比较哈希映射中的值。 我非常技术化,不太喜欢编程,尝试学习。

2 个答案:

答案 0 :(得分:1)

这是你可以做到的一种方式:

#!/usr/bin/env perl
use strict;
use warnings;

my %msg_to_number = ( 
     'Hello World, I am XYZ'    => 11,
     'I am using Stack Overflow for Guidance'   => 12,
     'Programming is good!' => 13,
);

my $str_to_match = 'Hello World, I am XYZ!';
#note - grep returns a list. We chuck any duplicate hits away. 
my ( $first_match ) = grep { $str_to_match =~ m/\Q$_\E/ } keys %msg_to_number;

print "$first_match   =  $msg_to_number{$first_match}\n";

注意 - grep中的模式匹配是相反的。检查您的字符串是否与哈希中的键匹配,如果匹配,则返回该键。只有当您的密钥是主字符串的子字符串(或完全匹配)时,它才会起作用。

它只获得'第一'匹配,所以实际上 - 如果有重复,结果将是随机的。因此,请确保您的哈希键足够独特。

E.g:

my $str_to_match = 'Hello World, I am XYZ!Programming is good!!!!!one';
my ( $first_match ) = grep { $str_to_match =~ m/\Q$_\E/ } keys %msg_to_number;
print "$first_match   =  $msg_to_number{$first_match}\n";

随意给你:

Programming is good!   =  13
Hello World, I am XYZ   =  11

作为替代方案 - 一种可能性是对输入/输出执行共同转换,这使得它对差异“盲目”。

E.g。

#!/usr/bin/env perl
use strict;
use warnings;

my %msg_to_number = ( 
     'Hello World, I am XYZ'    => 11,
     'I am using Stack Overflow for Guidance'   => 12,
     'Programming is good!' => 13,
);

my $str_to_match = 'Hello World, I am XYZ!!!!!';
my $transformed_match = $str_to_match =~ s/\W//gr;

my ( $first_match ) = grep { s/\W//gr =~ m/^\Q$transformed_match\E$/i } keys %msg_to_number;
print "$first_match   =  $msg_to_number{$first_match}\n";

这剥离\W这是“非字”字符(如标点符号和空白字符)并将两者进行比较。这意味着你的匹配有点模糊,并允许任意感叹号,间距等。

如果你想处理一个默认情况,那么非常方便。 //运营商就是您想要的。

return $msg_to_number{$first_match} // "default value here " ;

(或者您可以在$first_match上定义测试)

对于大小写insentive匹配,正则表达式的i修饰符将执行第二个示例中的技巧。

答案 1 :(得分:-1)

您可以使用=~类似报价的运算符在qr运算符之外编译正则表达式。这种方法的缺点是现在你必须迭代搜索键以查看是否有任何模式匹配。它比简单的哈希查找要慢得多。

use constant MAP_MESSAGE_TO_NUMBER => (
  [qr/Hello World, I am XYZ/,                  11],
  [qr/I am using Stack Overflow for Guidance/, 12],
  [qr/Programming is good!/,                   13],
);

my $Strtomatch = 'Hello World, I am XYZ!';
if ($some_condition) {
  foreach my $map (MAP_MESSAGE_TO_NUMBER) {
    my ($pattern, $val) = @$map;
    if ($Strtomatch =~ $pattern) {
      # some code will use the return value 
      doSomethingWith $val;
      # optionally exit the loop at this point with `last`, or store multiple match results 
    }
  }
  # optionally check if any match was found and print an error if not
}

我们不能使用哈希作为主数据结构,因为我们的正则表达式将变得无法使用,所以我在这里使用了一个数组数组。如果你想使用哈希,你可以看看Tie :: RegexpHash和/或Tie :: Hash :: Regex。