我正在尝试使用散列切片从复杂的散列中整理出已定义的参数。哈希切片很棒,因为它们避免了很多 foreach
和 if defined
,因此它们大大简化了语法。
但是,我显然没有正确地做到这一点:
use DDP;
my %hash = (
'a' => # first patient
{
'age' => 9,
'BMI' => 20
},
'b' =>
{
'age' => 8
}
);
my %defined_patients = grep {defined $hash{$_}{'age', 'BMI'}} keys %hash;
p %defined_patients;
上面的代码给出了一个空散列,当我希望它只返回患者 a
时。
这个问题类似于"no autovivication" pragma fails with grep in Perl我的代码基于它。
我也试过
my @defined_patients = grep {defined $hash{$_}{'age', 'BMI'}} keys %hash;
但这也不起作用。
我如何使用散列切片来 grep
具有定义键的患者?
最佳答案
如果你想检查没有一个目标键是未定义的,你必须单独检查。这 greps 未定义的值:
grep { ! defined } @{ $hash{$_} }{ qw(age BMI) }
注意散列切片
@{ $hash{$_} }{ qw(age BMI) }
在v5.24中,可以使用postfix dereferencing相反:
$hash{$_}->@{ qw(age BMI) }
但是 grep
必须适合另一个。由于您想要定义所有值的情况,因此必须否定内部 grep
的结果:
my @patients =
grep { ! grep { ! defined } $hash{$_}->@{ qw(age BMI) } }
keys %hash;
虽然这很丑陋。我可能会在子程序中做一些更简单的事情。这样您就可以轻松处理任意数量的键:
sub some_patients {
my( $hash, $keys ) = @_;
my @patient_keys;
foreach my $key ( keys %$hash ) {
next unless grep { ! defined } $hash{$key}->@{ @$keys };
push $key, @patient_keys;
}
return @patient_keys;
}
现在我只是简单地调用一个子程序而不是 grokking 多级 greps:
my @patient_keys = some_patients( \%patients, [ qw(age BMI) ] );
或者,对于更有针对性的东西,可能像这样测试特定的子哈希而不是整个数据结构:
sub has_defined_keys {
my( $hash, $keys ) = @_;
! grep { ! defined } $hash->@{@$keys}
}
my @target-keys = ...;
my @keys = grep {
has_defined_keys( $patients{$_}, \@target-keys )
} keys %patients;
无论哪种方式,当事情开始变得有点太复杂时,使用子例程为这些东西命名,这样您就可以隐藏代码以支持简短的东西。
关于Perl:如何使用哈希切片进行 grep?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67163500/