追加のハッシュルックアップを使用'が存在する'?
-
13-09-2019 - |
質問
こともあるのですがアクセスのハッシュのようになります:
if(exists $ids{$name}){
$id = $ids{$name};
}
ある良い練習?いてはちょっとしたことに懸念されるものではないがルックアップがって頂くことができます。であり、より良いチェックの存在割り当てるにはどのようなものか?
解決
確認 exists
, ご予防autovivification.見 Autovivification:何で、なぜ、いかに○をつけてください。.
更新: として trendels ポイントいたしましたので、autovivificationないしそれを実現するためには、この例で掲載しています。いと仮定すると、実際のコードをマルチレベルのハッシュ.
こちらのイラストです:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my (%hash, $x);
if ( exists $hash{test}->{vivify} ) {
$x = $hash{test}->{vivify}->{now};
}
print Dumper \%hash;
$x = $hash{test}->{vivify}->{now};
print Dumper \%hash;
__END__
C:\Temp> t
$VAR1 = {
'test' => {}
};
$VAR1 = {
'test' => {
'vivify' => {}
}
};
他のヒント
あなたは<のhref = "http://search.cpan.org/~nwclark/perl-5.8.9/ext/Hash/Util/lib/Hash/Util.pm" のrel = "nofollowをnoreferrerを適用し使用することができますハッシュへの「>ハッシュ:: Utilののさんlock_keys。その後、evalの中にあなたの割り当てを行います。
#!/usr/bin/perl
use Hash::Util qw/lock_keys/;
my %a = (
1 => 'one',
2 => 'two'
);
lock_keys(%a);
eval {$val = $a{2}}; # this assignment completes
eval {$val = $a{3}}; # this assignment aborts
print "val=$val\n"; # has value 'two'
あなたはこのようなもののルックアップでそれを行うことができます:
$tmp = $ids{$name};
$id = $tmp if (defined $tmp);
私はそれがボトルネックだったことを見ない限り、しかし、私は気にしないでしょう。
それはあなたがこれを行うことができ、マルチレベルのハッシュがない場合:
$id = $ids{$name} || 'foo';
または$ idはすでに値を持っている場合:
$id ||= $ids{$name};
「fooが」デフォルトまたはフォールスルーの値です。それは、マルチレベルのハッシュである場合は、autovivificationが問題になるだろうされていない場合は、それを使用し、以前のスレッドで議論autovivificationを避けたりしないように「存在する」を使用します。
私はこのイディオムを書き込むために使用しています:
my %h;
for my $key (@some_vals) {
...
$h{$key} = undef unless exists $h{$key};
...
}
return keys %h;
このコードは、一般的に使用される$h{$key}++
よりも少し速いです。 exists
無駄な割り当てを回避しundef
値のための割り当てを回避します。あなたのためのベストの答えは次のとおりです。ベンチマークに!私はexists $ids{$name}
が少し速く$id=$ids{$name}
よりも、あなたは大きなミス率を持っている場合と、あなたのバージョンが存在する割り当てと後の試験よりも速いことを推測します。
たとえば、私はこのようなものを書いたでしょう。
sub intersect {
my $h;
@$h{@{shift()}} = ();
my $i;
for (@_) {
return unless %$h;
$i = {};
@$i{grep exists $h->{$_}, @$_} = ();
$h = $i;
}
return keys %$h;
}
のパフォーマンスは、この場合には重要ではありません「のDevel :: NYTProf」を参照してください。 しかし、あなたの質問に答えるます:
ハッシュの値が存在しない場合は、、非常に高速です。
「存在」if(exists $ids{$name}){
$id = $ids{$name};
}
が、それがない場合は第2のルックアップが行われている存在。 値がそうである場合に高速になります唯一のルックアップを行うよりも、存在している。
$id = $ids{$name};
if($id){
#....
}
perlのメーリング・リストから、このLITTELベンチマークを参照してください。
#!/usr/bin/perl -w
use strict;
use Benchmark qw( timethese );
use vars qw( %hash );
@hash{ 'A' .. 'Z', 'a' .. 'z' } = (1) x 52;
my $key = 'xx';
timethese 10000000, {
'defined' => sub {
if (defined $hash{$key}) { my $x = $hash{$key}; return $x; };
return 0;
},
'defined_smart' => sub {
my $x = $hash{$key};
if (defined $x) {
return $x;
};
return 0;
},
'exists' => sub {
if (exists $hash{$key}) { my $x = $hash{$key}; return $x; };
return 0;
},
'as is' => sub {
if ($hash{$key}) { my $x = $hash{$key}; return $x; };
return 0;
},
'as is_smart' => sub {
my $x = $hash{$key};
if ($x) { return $x; };
return 0;
},
};
勝者である「存在する」は、その番組を存在しないキー(「XX」)を使用。
Benchmark: timing 10000000 iterations of as is, as is_smart, defined, defined_smart, exists...
as is: 1 wallclock secs ( 1.52 usr + 0.00 sys = 1.52 CPU) @ 6578947.37/s (n=10000000)
as is_smart: 3 wallclock secs ( 2.67 usr + 0.00 sys = 2.67 CPU) @ 3745318.35/s (n=10000000)
defined: 3 wallclock secs ( 1.53 usr + 0.00 sys = 1.53 CPU) @ 6535947.71/s (n=10000000)
defined_smart: 3 wallclock secs ( 2.17 usr + 0.00 sys = 2.17 CPU) @ 4608294.93/s (n=10000000)
exists: 1 wallclock secs ( 1.33 usr + 0.00 sys = 1.33 CPU) @ 7518796.99/s (n=10000000)
「is_smartとして」が勝者であることを示しているが存在し、キーを(「X」)を使用します。
Benchmark: timing 10000000 iterations of as is, as is_smart, defined, defined_smart, exists...
as is: 3 wallclock secs ( 2.76 usr + 0.00 sys = 2.76 CPU) @ 3623188.41/s (n=10000000)
as is_smart: 3 wallclock secs ( 1.81 usr + 0.00 sys = 1.81 CPU) @ 5524861.88/s (n=10000000)
defined: 3 wallclock secs ( 3.42 usr + 0.00 sys = 3.42 CPU) @ 2923976.61/s (n=10000000)
defined_smart: 2 wallclock secs ( 2.32 usr + 0.00 sys = 2.32 CPU) @ 4310344.83/s (n=10000000)
exists: 3 wallclock secs ( 2.83 usr + 0.00 sys = 2.83 CPU) @ 3533568.90/s (n=10000000)