prashantpal84 has asked for the wisdom of the Perl Monks concerning the following question:

%hash = (a=>1,b=>2); $count = 0; while(($key,$value) = each %hash) { $count++ if $value==keys(%hash); } print $count;
why its going in infinite loop??????

Replies are listed 'Best First'.
Re: hash and while
by jwkrahn (Abbot) on Aug 05, 2010 at 06:12 UTC

    Because each iterates over each key and value and keys and values reset that iterator back to the beginning.

    You want to get the value of keys before you iterate through the hash with each:

    my %hash = qw( a 1 b 2 ); my $count = 0; my $key_count = keys %hash; while ( my ( $key, $value ) = each %hash ) { $count++ if $value == $key_count; } print $count;
      awsome!!!!
      just one question.. there must be iterator variable... do u no which is that???
      Thanks

        Each hash has its own iterator variable, but this variable is not explicitly accessible to humble monks such as you and I. No doubt a way may be found through inline C code or perhaps through tie, but other, more subtle and puissant monks must assist you in this.

Re: hash and while
by Ratazong (Monsignor) on Aug 05, 2010 at 06:20 UTC

    jwkrahn was faster than me. Nevertheless some hints:

    If you suspect an infinite loop, try to find out what is looping, e.g. with the following code:

    while((my $key,my $value) = each %hash) { print "$key - $value\n"; $count++ if $value==keys(%hash); }
    Then you would have seen that only the first element is accessed.

    After that, you might want to comment out parts uncommon to you, e.g. by

    while((my $key,my $value) = each %hash) { print "$key - $value\n"; $count++; # if $value==keys(%hash); }
    Now you see that the each works fine.

    In a third step, google for "perl keys each" - and you'll find the exact reason and link as provided by jwkrahn.

    HTH, Rata
Re: hash and while
by roboticus (Chancellor) on Aug 05, 2010 at 13:07 UTC

    prashantpal84:

    You've already gotten some great information about the problem and ways to fix it. If you want to make the minimum changes to your program, you can take advantage of the fact that the number of keys in your hash doesn't change during your loop. So you can evaluate it once and then store it in a temporary variable for use during your loop, like so:

    %hash = (a=>1,b=>2); $count = 0; $hash_key_count = keys(%hash); while(($key,$value) = each %hash) { $count++ if $value==$hash_key_count; } print $count;

    This way, you don't reset the each iterator each time through the while loop.

    ...roboticus