list - Unexpectedly short Perl slices -


the following snippet of perl supposed print first 5 items of array referenced hash value, or fewer if array shorter.

while ( ($key,$value) = each %groups ) {    print "$key: \n";    @list = grep defined, @{$value};    @slice = grep defined, @list[0..4];    foreach $item ( @slice ) {       print "   $item \n";    }    print "   (", scalar @slice, " of ", scalar @list, ")\n"; } 

i don't think first grep defined necessary, can't harm, , should guarantee there no undefined array members before slice. second grep defined remove undefined array members in result of slice when @list shorter 5.

%groups has been populated repeated invocations of:

  $groups{$key} = () unless defined $groups{$key};   push @{$groups{$key}}, $value; 

most of time works fine:

key1:    value1    value2    value3    value4    value5    (5 of 100) 

but -- , haven't worked out under circumstances -- see:

key2:    value1    (1 of 5)  key3:    value1    value2    (2 of 5) 

i expect length of printed list, , x (x of y) min(5,y)

what cause behaviour?

using grep array slice @list autovivifies elements , extends array.

@foo = (1,2,3); @bar = @foo[0..9999]; print scalar @foo;             # =>  3  @foo = (1,2,3); @bar = grep 1, @foo[0..9999]; print scalar @foo;             # => 10000 

this happens in other contexts perl wants loop on array slice.

@foo = (1,2,3); foreach (@foo[0..9999]) { } print scalar @foo;             # => 10000  @foo = (1,2,3); @bar = map { } @foo[0..9999]; print scalar @foo;             # => 10000 

so workarounds?

  1. use more complicated expression range or grep operand

    @bar = grep 1, @foo[0..(@foo>=9999?9999:$#foo)]; @bar = grep 1, @foo>=9999 ? @foo[0..9999] : @foo; 
  2. use temporary array variable

    @bar = grep 1, @tmp=@foo[0..9999] 
  3. (suggested @fmc) use map set intermediate array

    @bar = grep 1, map { $list[$_] } 0..9999; 
  4. work array indices rather directly array

    @bar_indices = grep defined($foo[$_]), 0..9999; @bar = @foo[@bar_indices];  @bar = @foo[  grep defined($foo[$_]), 0..9999 ]; 

Comments

Popular posts from this blog

java - Jmockit String final length method mocking Issue -

asp.net - Razor Page Hosted on IIS 6 Fails Every Morning -

c++ - wxwidget compiling on windows command prompt -