« ハッシュを高速に操作したい (データ追加) | メイン | 文字列を文字コードへ変換する »

カテゴリー:ハッシュ(連想配列) 

ハッシュのキーを挿入(追加)した順番通りに取り出す

このエントリーを含むはてなブックマーク  livedoorクリップ  ハッシュのキーを挿入(追加)した順番通りに取り出すをdel.icio.usに追加  ハッシュのキーを挿入(追加)した順番通りに取り出すをYahoo!ブックマークに追加  ハッシュのキーを挿入(追加)した順番通りに取り出すをニフティクリップに追加

通常、ハッシュに入れた値をkeysなどを使って取り出すと、配列のように追加した順番通りに並ぶことはまずないといってもよいし、期待してはならない。この問題を解決するには、つまりハッシュに順番を保持させる簡単な方法は「Tie::IxHash」モジュールを使用することだろう。

「Tie::IxHash」モジュールは、最初にtieで関連づけさせれば、後は通常通りkeysなどで操作すればよい。解除したくなったらuntieでOKだ。

;#
;#順番通りにハッシュから取り出す
;#

use Tie::IxHash;

#---------------------------------------#
#準備する
#---------------------------------------#
#-- ハッシュとの関連づけ --#
tie %hash, 'Tie::IxHash';

#-- ハッシュに値を代入 --#
%hash = (
      'a' => 1
	, 'b' => 2
	, 'c' => 3
	, 'd' => 4
	, 'e' => 5
);


#---------------------------------------#
#表示
#---------------------------------------#
foreach my $key ( keys %hash ){
    print "$key,$hash{$key}\n";
}


○実行結果
a,1
b,2
c,3
d,4
e,5


「Tie::IxHash」モジュールは標準ではインストールされない。CPANからダウンロード、インストールする必要がある。
なお、このモジュールはPerlのみで書かれている(PurePerlの)ため、解凍後、ファイルを適当なディレクトリに置いて呼び出せば特に問題なく使用できる。

もし、本当に「Tie::IxHash」モジュールが効いているか疑うのなら、use, tieの行をコメントアウトして実行してみればよい。

ただし、使用する際に次の点に注意する必要がある。

■関連づけの前に入れた値は無効
当たり前の話ではありますが、tieした以降に代入された値にのみ有効。tieした瞬間にハッシュは真っ白な状態に。最初に入れたデータはuntieすれば関連付け前の値が取り出せるようになる。

use Tie::IxHash;

#-- ハッシュに値を代入 --#
%hash = (
      'a' => 1
	, 'b' => 2
	, 'c' => 3
);

#-- ハッシュとの関連づけ --#
tie %hash, 'Tie::IxHash';


■無名ハッシュには使えない(ハズ)
次のようなハッシュを組んだ場合、一番最初のキーにはIxHashが効くが、それ以降の無名ハッシュ部分には効かない。以下の例だと、'muscat', 'apple', 'banana'の順番は保証されるが、それ以降の'price','santi','omosa'については出鱈目(でたらめ)な順番で取り出される。

use Tie::IxHash;

#-- ハッシュとの関連づけ --#
tie %hash, 'Tie::IxHash';

#-- ハッシュに値を代入 --#
%hash = (
      'muscat' => { price=>500, santi=>'おかやま', omosa=>150 }
    , 'apple'  => { price=>200, santi=>'あおもり', omosa=>250 }
    , 'banana' => { price=>130, santi=>'たいわん', omosa=>130 }
);

これをTie::IxHashで解決するならば次のようにする。

use Tie::IxHash;

#-- ハッシュとの関連づけ --#
tie %hash,     'Tie::IxHash';
tie %h_muscat, 'Tie::IxHash';
tie %h_apple,  'Tie::IxHash';
tie %h_banana, 'Tie::IxHash';

#-- ハッシュに値を代入 --#
%h_muscat = (price=>500, santi=>'おかやま', omosa=>150);
%h_apple  = (price=>200, santi=>'あおもり', omosa=>250);
%h_banana = (price=>130, santi=>'たいわん', omosa=>130);

%hash = (
      'muscat' => \%h_muscat 
    , 'apple'  => \%h_apple
    , 'banana' => \%h_banana
);

#-- 表示 --#
foreach my $key1 ( keys %hash ){
    print "$key1\n";
    foreach my $key2 ( keys %{$hash{$key1}} ){
        print "    $key2=", $hash{$key1}->{$key2}, "\n"
    }
}

次のように配列としてデータを持ち、取り出すときにハッシュとすることでも実現できる。

use Tie::IxHash;

#------------------------------------------#
#                準  備                    #
#------------------------------------------#
#-- ハッシュとの関連づけ --#
tie %hash, 'Tie::IxHash';

#-- ハッシュに値を代入 --#
%hash = (
      'muscat' => [price=>500, santi=>'おかやま', omosa=>150]
    , 'apple'  => [price=>200, santi=>'あおもり', omosa=>250]
    , 'banana' => [price=>130, santi=>'たいわん', omosa=>130]
);

#------------------------------------------#
#                表  示                    #
#------------------------------------------#
foreach my $key ( keys %hash ){
   my %tmp = ();

    #-- 関連づけ --#
    tie %tmp, 'Tie::IxHash';

    #-- 値の代入 --#
    %tmp = @{$hash{$key}};    #ハッシュもリストのうち

    #-- 表示 --#
    print "$key\n";
    foreach ( keys %tmp ){
        print "    $_ : $tmp{$_}\n";
    }

    untie %tmp;
}

よく(入門者の方に)誤解されるが、'=>'演算子は','演算子と優先順位が異なるだけで、意味はまったく同じである。単純にハッシュに代入する際、キーと値のペアをわかりやすくするなどの目的で設けているだけで、すべて','を使用してハッシュを初期化しても全く問題ない。

以上をふまえておけば、配列とハッシュの初期化方法はまったく同じだということがお分かりいただけるだろう。



■参考文献
Perlクックブック〈VOLUME1〉




トラックバック

このエントリーのトラックバックURL:
http://katsubemakito.net/mt/mt-tb.cgi/606

この一覧は、次のエントリーを参照しています: ハッシュのキーを挿入(追加)した順番通りに取り出す:

» [php][perl]perlのハッシュの順序をphpの連想配列みたいに保持したい from A Small, Good Thing - diary
皆さんご無沙汰しております。「phpのあれ、perlでどうやるの?」のコーナー第2回*1、今日はperlのハッシュの順序についてです。 phpの方が手に... [詳しくはこちら]

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

VPSレンタルサーバー




クリエイティブ・コモンズ・ライセンス
このブログは、次のライセンスで保護されています。 クリエイティブ・コモンズ・ライセンス.