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

qod*_*nja 1 perl hash key map

试图用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};
}   
Run Code Online (Sandbox Code Playgroud)

在这里用...

my $params_hash = $cgi->Vars();
my $scrubbed = $self->scrub_empty_params($params_hash) if $self->is_hash($params_hash);
Run Code Online (Sandbox Code Playgroud)

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

Eri*_*rom 6

在这一行:

my $scrubbed_hash = map { defined $hash_ref->{$_} ? ($_ => $hash_ref->{$_}) : () } keys %{$hash_ref};   
Run Code Online (Sandbox Code Playgroud)

您正在将标记分配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;
}   
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

print join ', ' => keys %hash;  # foo, baz
Run Code Online (Sandbox Code Playgroud)

每次更新:

scrub_empty_params方法应如下所示:

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

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

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

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

sub clean_vars {
    my ($self) = @_;
    $self->scrub_empty_params($self->Vars)
}
Run Code Online (Sandbox Code Playgroud)

  • for/foreach和map非常相似.最大的区别在于,如果您尝试使用循环构建列表.如果是这样,`我的@list = map {...} @ src`比`my @list更短更清晰; 推@list,...为@ src`.如果你只使用循环方面,使用`for`或`foreach`可以更清楚地表明你的意图,并且会更快一些. (2认同)
  • 特别是,`foreach`结构理解`1 .. 10000`是一个范围,并且在循环开始之前不会创建所有数字.而`map {...} 1 .. 10000`必须在开始循环之前构建范围内的所有数字.换句话说,`for` /`foreach`具有比`map`更优化的情况. (2认同)