I can slice kes/values as next:
$item->%{ @cols }
But if some column does not exist at $item
It will be created at resulting hash.
Can I slice only defined values?
You can check whether they exist.
$item->%{ grep {exists $item->{$_}} @cols }
should do the job slicing only the existing values.
Anyway - simply accessing these values should NOT autovivify them. Only if you Pass these values as parameters to some function and they are implicetly aliased there, they are autovivified.
use strict;
use warnings;
use Data::Dumper;
my @cols =qw (a b c);
my $item = [{a => 1, c => 3}];
print Dumper({$item->[0]->%{ grep {exists $item->[0]->{$_}} @cols }});
print Dumper($item);
print Dumper({$item->[0]->%{ @cols }});
print Dumper($item);
print Dumper($item->[0]->%{ grep {exists $item->[0]->{$_}} @cols });
print Dumper($item);
print Dumper($item->[0]->%{ @cols }); ## Only here does autovivication take place
print Dumper($item);
Only the last print will generate the:
$VAR1 = [
{
'c' => 3,
'a' => 1,
'b' => undef
}
];
indicating that b got autovivified.
Use
$item->%{ grep { exists($item->{$_}) } @cols }
or
do { $item->%{ @cols } }
Indexing/slicing a hash does not add elements to it.
my @cols = qw( a b c );
my $item = { };
say 0+%$item; # 0
my @kvs = $item->%{ @cols };
say 0+%$item; # 0 ok
Except when it's used as an lvalue (assignable value, such as when on the left-hand side of =
).
my @cols = qw( a b c );
my $item = { };
say 0+%$item; # 0
1 for $item->%{ @cols };
say 0+%$item; # 3 XXX
You could filter out the keys of elements that don't exist.
my @cols = qw( a b c );
my $item = { };
say 0+%$item; # 0
1 for $item->%{ grep { exists($item->{$_}) } @cols };
say 0+%$item; # 0 ok
But the simple solution is to not use it as an lvalue.
my @cols = qw( a b c );
my $item = { };
say 0+%$item; # 0
1 for do { $item->%{ @cols } };
say 0+%$item; # 0 ok
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With