如何从哈希中删除未定义的键?

时间:2011-10-05 20:52:23

标签: perl hash map key

尝试使用map和grep来解决这个问题,任何想法都错了吗?我一直在接受 当我尝试打印新哈希的值时,不能使用字符串(“10”)作为HASH参考,而“严格参考”错误

sub scrub_hash{
    my($self,$hash_ref) = @_;
    my $scrubbed_hash = map { defined $hash_ref->{$_} ? ($_ => $hash_ref->{$_}) : () } keys %{$hash_ref};   
    print STDERR "[scrub]". $_."\n"  for values %{$scrubbed_hash};
}   

在这里使用 ...

my $params_hash = $cgi->Vars();
my $scrubbed = $self->scrub_empty_params($params_hash) if $self->is_hash($params_hash);

在这种情况下,通过帖子提交表单时未定义的参数仍然显示为key1 =& key2 =所以scrub将关闭em

2 个答案:

答案 0 :(得分:6)

在这一行:

my $scrubbed_hash = map { defined $hash_ref->{$_} ? ($_ => $hash_ref->{$_}) : () } keys %{$hash_ref};   

您正在将map的列表分配到标量$scrubbed_hash。标量上下文中的map将返回列表中元素的数量(10)。

不是分配给标量,而是分配复数哈希:

sub scrub_hash{
    my($self,$hash_ref) = @_;
    my %scrubbed_hash = map { defined $hash_ref->{$_} ? ($_ => $hash_ref->{$_}) : () } keys %{$hash_ref};   
    print STDERR "[scrub]". $_."\n"  for values %scrubbed_hash;
}   

如果你真的想为$scrubbed_hash使用标量,你需要用{map {...} args}包装map语句,这将在列表中构造一个匿名哈希。

要过滤掉适当的元素,您可以使用delete函数:

my %hash = (foo => 1, bar => undef, baz => 2);

defined $hash{$_} or delete $hash{$_} for keys %hash;

print join ', ' => keys %hash;  # foo, baz

根据更新:

scrub_empty_params方法应如下所示:

sub scrub_empty_params {
    my ($self, $hash) = @_;
    {map {defined $$hash{$_} ? ($_ => $$hash{$_}) : ()} keys %$hash}
}

如果这对您不起作用,则可能是您的值已定义,但长度为0。

sub scrub_empty_params {
    my ($self, $hash) = @_;
    {map {(defined $$hash{$_} and length $$hash{$_}) ? ($_ => $$hash{$_}) : ()} keys %$hash}
}

您可能希望通过创建返回已过滤哈希的其他->Vars()方法从API中删除一些样板:

sub clean_vars {
    my ($self) = @_;
    $self->scrub_empty_params($self->Vars)
}

答案 1 :(得分:2)

试试这个:

    my %scrubbed_hash = map { $_ => $hash_ref->{ $_ } } grep { defined $hash_ref->{$_} } keys %{$hash_ref};