Do I need to reset a Perl hash index?

2019-07-21 03:52发布

OK, this is a N00b question, but it's gotten me stumped:

I have the following Perl code:

%project_keys = (
  cd     => "continuous_delivery",
  cm     => "customer_management",
  dem    => "demand",
  dis    => "dis",
  do     => "devops",
  sel    => "selection",
  seo    => "seo"
);

print "proj_code is $proj_code\n";
while ( ($key, $value) = each %project_keys ) {
    if ($key == $proj_code) {
        $url = "http://projects/".$project_keys{$key}."/setter";
        last;
    }
}

$proj_code is always passed in the same ('dis') and the print line shows that.

However, each time I run this, I'm getting a different value for project_keys{$key}.

What (no doubt obvious) thing am I doing wrong? I have seen comments about how each is 'fragile' - is that it?

标签: perl hash
3条回答
做自己的国王
2楼-- · 2019-07-21 04:20

Yes, if you use each to iterate through a hash but don't iterate all the way till no result is returned, you will pick up the next time where you left off.

You can reset the internal iterator to the beginning by using keys or values before looping, like so:

keys(%project_keys);
while ( ($key, $value) = each %project_keys ) {

That said, you have a number of other problems:

Use eq, not ==, to test for string equality.

Your whole loop is pointless; you don't need to iterate through a hash to look up a value; the loop can be replaced with simply doing:

if ( exists $project_keys{$proj_code} ) {
    $url = "http://projects/$project_keys{$proj_code}";
}
查看更多
做自己的国王
3楼-- · 2019-07-21 04:25

If you already have the "key" you're expecting, check if it exists and use it...

Also, always use use strict; use warnings;

#!/usr/bin/perl

use strict;
use warnings;

my $proj_code= 'dis';
my $url;

my %project_keys = (
  cd     => "continuous_delivery",
  cm     => "customer_management",
  dem    => "demand",
  dis    => "dis",
  do     => "devops",
  sel    => "selection",
  seo    => "seo"
);

$url = "http://projects/$project_keys{$proj_code}/setter" 
    if exists $project_keys{$proj_code};

print "url: $url\n";

OUTPUTS:

url: http://projects/dis/setter
查看更多
▲ chillily
4楼-- · 2019-07-21 04:35

You're using each. Best not to. It's subtle and stores state within the hash.

Far better than

while( my ( $key, $value ) = each %hash ) {
   ...
}

is to use a foreach loop on the keys function

foreach my $key ( keys %hash ) {
   my $value = $hash{$key};
   ...
}
查看更多
登录 后发表回答