masatoの日記

やっていきます

Perlで順番を保ったまま要素をユニークにしたい

ダブりのあるたくさんの要素を並び順を保ったままダブりなくしたいというニーズ。

Linuxのsort+uniqコマンドだと並び順が変わってしまう。Perlのハッシュを使ってダブりをなくしても並び順は変わってしまう。ハッシュでは元の並び順が保証されないからだ。

そこでハッシュでありながら並び順を保つことができるモジュールTie::IxHashの出番だ。こいつを使うと、ハッシュに入れた順番が記憶される。ループさせて元の順で読み出すことができる。

使い方。

use Tie::IxHash;
tie my %ordered_hash, "Tie::IxHash";

while(<DATA>) {
  chomp;
  $ordered_hash{$_}++;
}

__DATA__
1 tofu
2 hakusai
3 daikon
4 kabocha
5 shimeji

まずモジュールをuseする。したら、ハッシュをtieする。tieというのはtie関数であるらしい。perldocに解説がある。(http://perldoc.jp/func/tie)。ということで、第2引数の"Tie::IxHash"は必須だ。

このハッシュでは値の並び順が保たれることになる。

そして、DATAからサンプルデータを読み込んでみる。番号通りに読み出せるかみてみよう。

use Data::Dumper;

print Dumper \%ordered_hash;

結果。

$VAR1 = {
          '1 tofu' => 1,
          '2 hakusai' => 1,
          '3 daikon' => 1,
          '4 kabocha' => 1,
          '5 shimeji' => 1
        };

順番通りだ。

使いどころ

複数の同じ文を含む文章などで、基本的に並び順のままにしておきたいのだけれど、重複する文は省きたい場合。具体的には試験要領書、チェックリストなど。箇条書きの部分でダブってることが多い。こうしておくと、CATツールを使ってその文書を翻訳するときに同じ文を見なくて済むようになる。乱暴かもしれないけど。