Perl:如何使用哈希切片进行 grep?

Perl: How to grep with Hash Slices?

我正在尝试使用散列切片从复杂的散列中整理出已定义的参数。哈希切片很棒,因为它们避免了很多 foreachif 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;

上面的代码给出了一个空散列,当我想要它时 return 只是耐心 a.

这个问题类似于 ,我的代码基于它。

我也试过了

my @defined_patients = grep {defined $hash{$_}{'age', 'BMI'}} keys %hash;

但这也不管用。

如何将散列切片用于 grep 具有定义键的患者?

如果要检查none个目标键是否未定义,则需要单独检查。这 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;

无论哪种方式,当事情开始变得有点太复杂时,使用子例程为这些东西命名,这样您就可以隐藏代码以支持简短的东西。