Perl 如何确定哈希在赋值中的元素数是否为奇数?

Perl 如何确定哈希在赋值中的元素数是否为奇数?,perl,hash,Perl,Hash,我怎样才能知道这个散列是否有奇数个元素 my %hash = ( 1, 2, 3, 4, 5 ); 好的,我应该写更多的信息 sub routine { my ( $first, $hash_ref ) = @_; if ( $hash_ref refers to a hash with odd numbers of elements ) { "Second argument refers to a hash with odd numbers of elemen

我怎样才能知道这个散列是否有奇数个元素

my %hash = ( 1, 2, 3, 4, 5 );
好的,我应该写更多的信息

sub routine {
    my ( $first, $hash_ref ) = @_;
    if ( $hash_ref refers to a hash with odd numbers of elements ) {
        "Second argument refers to a hash with odd numbers of elements.\nFalling back to default values";
        $hash_ref = { option1 => 'office', option2 => 34, option3 => 'fast'  };
    }
    ...
    ...
}


routine( [ 'one', 'two', 'three' ], { option1 =>, option2 => undef, option3 => 'fast' );

答案很简单:你会得到一个警告:

Odd number of elements in hash assignment at...
假设你没有傻到把警告关掉

难的答案是,一旦完成了对散列的赋值(并发出警告),它就不再奇怪了。所以你不能

my %hash = (1,2,3,4,5);
use Data::Dumper;
print Dumper \%hash;

$VAR1 = {
      '1' => 2,
      '3' => 4,
      '5' => undef
    };
如您所见,
undef
已插入到空位中。现在,您可以检查未定义的值,并假设任何现有的未定义值构成散列中奇数个元素。然而,如果未定义的值是散列中的有效值,那么您就有麻烦了

perl -lwe '
    sub isodd { my $count = @_ = grep defined, @_; return ($count % 2) }; 
    %a=(a=>1,2); 
    print isodd(%a);'
Odd number of elements in hash assignment at -e line 1.
1

在这一行程序中,函数
isodd
对定义的参数进行计数,并返回参数数量是否为奇数。但正如你所看到的,它仍然给出了警告。

好吧,我想在这个问题上有一些术语上的混乱,应该加以澄清

Perl中的散列总是具有相同数量的键和值,因为它基本上是一个通过键存储某些值的引擎。我的意思是,这里应该将键值对视为单个元素。)

但我想这并不是真正的问题。)我猜想OP试图从一个列表(不是一个数组——差别很小,但它仍然存在)构建一个哈希,并得到了警告

因此,关键是检查列表中将分配给散列的元素的数量。它可以做的很简单

my @list = ( ... there goes a list ... ); 
print @list % 2; # 1 if the list had an odd number of elements, 0 otherwise
请注意,
%
操作符将标量上下文强加给列表变量:它简单而优雅。)

更新如我所见,问题略有不同。好的,让我们讨论一下给出的例子,稍微简化一下

my $anhash = { 
   option1 =>, 
   option2 => undef, 
   option3 => 'fast'
};
看,
=>
只是一种语法糖;这个作业可以很容易地改写为

my $anhash = { 
   'option1', , 'option2', undef, 'option3', 'fast'
};
关键是第一个逗号后缺少的值和
undef
不一样,因为列表(任何列表)在Perl中都会自动展平
undef
可以是任何列表的常规元素,但空的空间将被忽略

请注意,如果调用过程时引用了包装无效的哈希,则在调用过程之前将引发您关心的警告(如果设置了
use warnings
)。因此,不管是谁造成的,都应该自己处理,看看自己的代码:他们说,尽早失败。)

您想使用命名参数,但为缺少的参数设置一些默认值?使用以下技巧:

sub test_sub {
  my ($args_ref) = @_;
  my $default_args_ref = {
    option1 => 'xxx',
    option2 => 'yyy',
  };
  $args_ref = { %$default_args_ref, %$args_ref,  };
}
那么你的测试可能会被这样称呼

test_sub { option1 => 'zzz' };
。。。甚至

test_sub {};

当散列分配不正确时,您可以使用
\uuuuu WARN\uuuu
信号来“陷阱”

use strict ;
use warnings ;

my $odd_hash_length = 0 ;   
{
  local $SIG{__WARN__} = sub {
    my $msg = shift ;
    if ($msg =~ m{Odd number of elements in hash assignment at}) {
      $odd_hash_length = 1 ;
    }
  } ;

  my %hash = (1, 2, 3, 4, 5) ;
}

# Now do what you want based on $odd_hash_length
if ($odd_hash_length) {
  die "the hash had an odd hash length assignment...aborting\n" ;
} else {
  print "the hash was initialized correctly\n";
}

另请参见。

好的解释。我喜欢四行一行。:)@sid_com好吧,不,在将参数分配给散列之前,您仍然可以对参数进行计数。然后用合适的方法处理它。@simbabque断线纯粹是为了视觉效果=假设在我的例子中列表作为散列引用传递时,这不起作用?在这种解决方案中,我也在思考,但在我看来它太不稳定了。