如何仅对定义的值进行切片?

How to slice only defined values?

我可以切片 kes/values 作为下一个:

$item->%{ @cols }

但是如果某些列在 $item 中不存在,它将在结果哈希中创建。

我可以只切片定义的值吗?

您可以检查它们是否存在。

$item->%{ grep {exists $item->{$_}} @cols }

应该只对现有值进行切片。

无论如何 - 简单地访问这些值不应该自动激活它们。仅当您将这些值作为参数传递给某个函数并且它们在那里隐式别名时,它们才会自动生成。

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);

只有最后一次打印会生成:

$VAR1 = [
          {
            'c' => 3,
            'a' => 1,
            'b' => undef
          }
        ];

表明 b 已自动激活。

使用

$item->%{ grep { exists($item->{$_}) } @cols }

do { $item->%{ @cols } }

Indexing/slicing 哈希不会向其添加元素。

my @cols = qw( a b c );
my $item = { };
say 0+%$item;                     # 0
my @kvs = $item->%{ @cols };
say 0+%$item;                     # 0 ok

除非它被用作左值(可分配的值,例如在 = 的左侧)。

my @cols = qw( a b c );
my $item = { };
say 0+%$item;                     # 0
1 for $item->%{ @cols };
say 0+%$item;                     # 3 XXX

您可以过滤掉不存在的元素的键。

my @cols = qw( a b c );
my $item = { };
say 0+%$item;                     # 0
1 for $item->%{ grep { exists($item->{$_}) } @cols };
say 0+%$item;                     # 0 ok

但简单的解决方案是不将其用作左值。

my @cols = qw( a b c );
my $item = { };
say 0+%$item;                     # 0
1 for do { $item->%{ @cols } };
say 0+%$item;                     # 0 ok