Do I need to reset a Perl hash index?

2019-07-21 04:18发布

问题:

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?

回答1:

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


回答2:

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:

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


标签: perl hash