什么是Perl相当于Python的dict.get(键,默认)?

时间:2017-04-26 11:20:02

标签: perl dictionary hashmap

Python与Perl的哈希值相对应的是dict(字典)对象。

如果d是Python dict,那么表达式

d.get(key, default)

...如果存在则评估为d[key],否则评估为default

除了三元表达式

之外,Perl是否对同一个想法有任何支持
exists $h{$key} ? $h{$key} : $default

3 个答案:

答案 0 :(得分:10)

Perl 5.10引入了defined-or operator //。你可以写:

$h{$key} // $default
  

//运算符与||具有相同的优先级和关联性。已经采取了特别的措施来确保这个操作符“尽你所能”而不破坏旧代码,但是涉及空正则表达式的一些边缘情况现在可能会以不同方式进行解析。

正如@Borodin在评论中指出的那样,这不会区分存在映射到未定义值的散列键与散列中根本不存在的键。

模块Hash::DefaultValue可能对此有所帮助。但是,虽然默认值可以是coderef,但它似乎并不直观地允许每次访问的任意默认值。另一个类似的模块是Hash::WithDefaults

您也可以使用

[$default, $h{$key}]->[exists $h{$key}]

但这并不比三元表达更有效,也更好看。当然,你可以自己动手代替:

use strict;
use warnings;

sub get_value_or_default(\%$$) {
    exists $_[0]->{$_[1]} ? $_[0]->{$_[1]} : $_[2];
}

my %hash = ( a => 1 );

print get_value_or_default(%hash, b => 33), "\n";
print get_value_or_default(%hash, b => 75), "\n";
print get_value_or_default(%hash, c => 96), "\n";

如果您喜欢冒险,可以将其写为:

use v5.24;
use warnings;

use feature 'signatures';
no warnings 'experimental::signatures';

sub get_value_or_default($hash, $key, $default) : prototype(\%$$) {
    exists $hash->{$key} ? $hash->{$key} : $default;
}

您没有为您的请求提供上下文,但Perl中设置默认值的常用方法是从另一个源读取的值被覆盖使用该构造:

my %config = (%$default_config, %{ get_config(...) });

答案 1 :(得分:5)

您可以使用已知的三元表达式

my $value_or_default = exists $h{$key} ? $h{$key} : $default

my $value_or_default = $h{$key} // $default ;

//已定义或运算符。

如果要交换到defined-or-operator,这取决于您的数据和需求。不同之处在于当您有一个未定义值的键时,您将得到不同的结果。

my %hash = ( key1 => undef ,
             key3 => 1 ) ;
my $default = 42 ;

foreach my $test ( qw(key1 key2 key3) ) {
  printf "%s => %s exists\n%s => %s defined-or\n\n" ,
         $test ,
         exists $hash{$test} ? $hash{$test} : $default ,
         $test ,
         $hash{$test} // $default ;
}

这导致:

Use of uninitialized value $hash{"key1"} in printf at x.pl line 11.
key1 =>  exists
key1 => 42 defined-or

key2 => 42 exists
key2 => 42 defined-or

key3 => 1 exists
key3 => 1 defined-or

对于 key1 ,密钥存在,但值未定义,因此perl会发出警告。

答案 2 :(得分:0)

您可以使用defined-or运算符:// 如果您希望默认值成为结构的一部分,请设置键'default':

my %h = (default => 'Some default value');
say $h{'notSet'} // $h{'default'};