あいつの日誌β

働きながら旅しています。

はじめてのハッシュスライス

ハッシュから特定のKeyに対する値を取り出す処理を考える。

で、その結果は配列に取得する。という処理を書いてたときの話です。最初はこんな感じのコードで書いていました。

my %hash = ( hoge => 0, fuga => 1, piyo => 2, moge => 3, moga => 4, mogo => 5 );
my @array = map { $hash{$_} } qw/hoge fuga piyo/;

なんですが、突然「これ、ハッシュスライスでも書けるなあ」と思いました。

my %hash = ( hoge => 0, fuga => 1, piyo => 2, moge => 3, moga => 4, mogo => 5 );
my @array = @hash{qw/hoge fuga piyo/};

ハッシュスライスを書くような場面に出会った事なかったのか、思いつかなかったのか分かりませんがたぶん初めてハッシュスライスを書いた気がします。
そしてハッシュスライスなじみがないせいか読みづらい...

どっちが高速なんだろう?

なのでベンチを取ってみて速度変わらなければハッシュスライスなんか二度と書かなければよいかと思ったのでベンチとってみた。

ベンチコード

#!/usr/bin/env perl
use strict;
use warnings;
use Benchmark qw/cmpthese timethese/;
my $count = 10_000_000;
my $message = 'hello, world';

my %hash = ( hoge => 0, fuga => 1, piyo => 2, moge => 3, moga => 4, mogo => 5 );

cmpthese timethese $count, {
    map => sub {
        my @array = map { $hash{$_} } qw/hoge fuga piyo/;
        $array[0] == 0 or die;
        $array[2] == 2 or die;
    },  

    slice => sub { 
        my @array = @hash{qw/hoge fuga piyo/};
        $array[0] == 0 or die;        
		$array[2] == 2 or die;
    },  
};

実行結果

:!perl bench/slice.pl
Benchmark: timing 10000000 iterations of map, slice...
       map: 10 wallclock secs (10.28 usr +  0.01 sys = 10.29 CPU) @ 971817.30/s (n=10000000)
     slice:  6 wallclock secs ( 6.30 usr + -0.01 sys =  6.29 CPU) @ 1589825.12/s (n=10000000)
           Rate   map slice
map    971817/s    --  -39%
slice 1589825/s   64%    --

ハッシュスライスは一応覚えておいたほうがいいなあ。