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

Dear Ladies and Gentlemen.

Why is it that a hash slice operand to grep,

eg print join "\n", grep /Yeah hoo!/, @x{@bigger_set_of_keys}

adds any missing keys to the hash ? Here's an example,

DB<38> undef %x DB<39> @x{5..10} = ('a' .. 'z')[0..6] DB<40> p join "\n", keys %x 8 10 9 5 6 7 DB<41> p join "\n", grep /a|b/, @x{5..7} a b DB<42> p join "\n", grep /a|b/, @x{1..10} a b DB<43> p join "\n", keys %x 1 10 2 3 4 5 6 7 8 9 DB<44>

Obviously, I am doing something stupid but what might that be ? Splitting the operation like

@my_values = @x{bigget_set_of_keys} ; @my_filtered_vals = grep /Yeah hoo!/, @my_values ;
works fine.

What is the best way of cascading slice operations ?

Thank you,

Yours sincerely.

  • Comment on Why is that a hash slice operand to grep adds keys to the hash (if the slice is bigger than the orig set of keys) ?
  • Select or Download Code

Replies are listed 'Best First'.
avoiding autovivification in hash slices
by blakem (Monsignor) on Nov 26, 2001 at 14:53 UTC
    You can get the keys w/o the autovivification like this:
    @my_filtered_keys = grep {exists $x{$_} && $x{$_} =~ /Yeah hoo!/} 1..1 +0;
    or the values w/o autovivification with map:
    @my_filtered_vals = map {exists $x{$_} && $x{$_} =~ /Yeah hoo!/ ? $x{$ +_} : ()} 1..10;
    Here is an example:
    #!/usr/bin/perl -wT use strict; my %x = ( 5 => 'a', 6 => 'b', 7 => 'Yeah hoo!', 8 => 'd', 9 => 'I said, Yeah hoo!', 10 => 'f' ); print "K:$_\n" for grep {exists $x{$_} && $x{$_} =~ /Yeah hoo!/} 1..10 +; print "V:$_\n" for map {exists $x{$_} && $x{$_} =~ /Yeah hoo!/ ? $x{$_ +} : ()} 1..10; print "X:$_\n" for keys %x; __END__ =head1 OUTPUT K:7 K:9 V:Yeah hoo! V:I said, Yeah hoo! X:7 X:8 X:9 X:10 X:5 X:6
    For more on autovivification see: Autovivification : What Is It and Why Do I Care? by by Uri Guttman.

    -Blake

Re: Why is that a hash slice operand to grep adds keys to the hash (if the slice is bigger than the orig set of keys) ?
by rje (Deacon) on Nov 27, 2001 at 01:50 UTC
    This also happens with code one of my friends is maintaining.
    On his machine (NT?), indexing an array beyond its 'top' element
    extends the array, and so a loop (which used to run fine) never
    terminates:

    my @main = ( "<UL>\n", "<!--begin-->\n", "</UL>\n" ); &getboardinfo(); sub getboardinfo { my($tnum); $msgcount = 0; $lastmsg = 0; $lastfu = 0; $fucount = 0; print STDERR "Going into loop: main is @main\n"; print STDERR "main has ", $#main + 1, " elements.\n"; for( $j=0; $j<=@main; $j++ ) { print STDERR "Loop! j is $j main[j] is $main[$j] main[j+2] is + $main[$j+2]\n";
    An illustration of the problem lies in the code above.
    The reference to $main[$j+2] extends the array, and so
    the loop goes on forever.
    if( $main[$j] =~ /<!--top: (.*)-->/ ) { $msgcount++; $lastmsg = $1; } elsif( $main[$j] =~ /<!--ins: (.*)-->/ ) { $tnum=$1; if( ( $main[$j+1] =~ /<!--end:/ ) &&( $main[$j+2] =~ /<!--end:/ ) ) { $lastfu = $tnum; $fucount++; } } } print STDERR "Done with loop\n"; return 0; }

    Of course, the original writer should probably have found
    a better way to write this loop (maybe by using foreach()).

    Rob