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?
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;
use temporary array variable
@bar = grep 1, @tmp=@foo[0..9999]
(suggested @fmc) use
map
set intermediate array@bar = grep 1, map { $list[$_] } 0..9999;
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
Post a Comment