字符串比较在Perl中的散列键 [英] string comparison for hash keys in perl

查看:121
本文介绍了字符串比较在Perl中的散列键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  MAP_MESSAGE_TO_NUMBER => {
'Hello World,我是XYZ'=> 11,
'我正在使用堆栈溢出进行指导'=> 12,
'编程很棒!'=> 13,
},

在我的Perl代码中,我试图用hash如果匹配发生,我只是返回相应的散列值(数字)。

我的代码工作正常。

  my $ Strtomatch ='Hello World,我是XYZ!'; 
if(some condition){
my $ val = MAP_MESSAGE_TO_NUMBER-> {$ Strtomatch};
#一些代码将使用返回值
doSomethingWith $ val;
}

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



我的问题是如何使这个更通用,以便即使部分字符串匹配。



即使很少的字符匹配它也可以返回值。



让我知道。



我不确定如何在这里使用正则表达式,因为我正在使用来自其他函数的值对哈希映射中的值进行比较。
我是技术性很强的人,不太擅长编程,试着去学习。

解决方案

做到这一点:

 #!/ usr / bin / env perl 
use strict;
使用警告;

my%msg_to_number =(
'Hello World,我是XYZ'=> 11,
'我正在使用Stack Overflow进行指导'=> 12,
'编程很好!'=> 13,
);

my $ str_to_match ='Hello World,我是XYZ!';
#note - grep返回一个列表。我们把任何重复的点击拿走。
my($ first_match)= grep {$ str_to_match =〜m / \ Q $ _\E /} keys%msg_to_number;

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

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

它只会得到'第一'的匹配,所以实际上说 - 如果有重复,结果将是随机的。所以确保你的散列键足够独特。



例如:

  my $ str_to_match ='Hello World,I是XYZ!编程很好!!!!!一个'; 
my($ first_match)= grep {$ str_to_match =〜m / \ Q $ _\E /} keys%msg_to_number;
print$ first_match = $ msg_to_number {$ first_match} \\\
;

会随机给出:

 编程很好! = 13 
Hello World,我是XYZ = 11

作为一种选择 - 一种可能性是对输入/输出执行一个共同的转换,这使得它对这些差异是盲目的。

例如

 #!/ usr / bin / env perl 
use strict;
使用警告;

my%msg_to_number =(
'Hello World,我是XYZ'=> 11,
'我正在使用Stack Overflow进行指导'=> 12,
'编程很好!'=> 13,
);

my $ str_to_match ='Hello World,我是XYZ !!!!!';
my $ transformed_match = $ str_to_match =〜s / \W // gr;
$ b $ my($ first_match)= grep {s / \W // gr =〜m / ^ \ Q $ transformed_match\E $ / i}键%msg_to_number;
print$ first_match = $ msg_to_number {$ first_match} \\\
;

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



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

 返回$ msg_to_number {$ first_match} //默认值在这里; 

(或者您可以在 $ first_match

对于不存在匹配的情况,正则表达式中的 i 修饰符将会像第二个例。

I am having an hash map in perl like this:

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

in my Perl code i am trying to make a match with hash key and if match happens i just return the corresponding hash value ( number ).

My code is working fine.

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;  
}

My question here is: if you will see the value of variable $Strtomatch has one extra character '!' which is not present in original hash map. So because of this my hash map does not returns any value.

My question is how can i make this more generic so that i can make comparison even if part of strings match.

even few characters match its fine to return the value.

Let me know.

I am not really sure how i can use regular expression here because i am doing comparison for a value in hash map with a value coming from other function. I am very technical and not too good with programming, trying things to learn.

解决方案

Here's one way you could do it:

#!/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";

Note - the pattern match in the grep is reversed. You check if your string matches a key in the hash, and return that if it does. It'll only work if your key is a substring (or exact match) of your primary string.

And it only gets a 'first' match, so practically speaking - if there are duplicates, the result will be random. So make sure your hash keys are sufficiently unique.

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";

Will give your randomly:

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

As an alternative - one possiblity is perform a common transform on input/output, which makes it 'blind' to the differences.

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";

This strips \W which is "not word" characters (like punctuation and whitespace) and compares the two like that. It means your matches are a bit fuzzier, and will allow arbitrary exclamation marks, spacing etc.

If you want to handle a default case, then the very handy. // operator is what you want.

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

(or you can just test defined on $first_match)

For case insentive matching, the i modifier to the regex will do the trick as in the second example.

这篇关于字符串比较在Perl中的散列键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆