Hashを使って配列をユニークにしよう!

軽く便乗。

use strict;
use warnings;
use Data::Dumper;

my @cars = qw/honda honda suzuki toyota toyota daihatu mitubishia/;

my %report = ();
for my $car ( @cars ) {
        $report{ $car }++;
}

print Dumper \%report;
http://perl-mongers.org/2008/06/hash.html

とありますが、単に配列をユニークにするだけの場合なら

my @cars = qw/honda honda suzuki toyota toyota daihatu mitubishia/;
my @uniq = do { my %h; grep { !$h{$_}++ } @cars };

print Dumper \@uniq;

といったようにgrepを使って簡素に書けます。

要素の出現順も守られるのでなかなかグーです。

またCPANモジュールのList::MoreUtilsのuniq関数でも同様のことができます。

use List::MoreUtils qw/uniq/;

my @cars = qw/honda honda suzuki toyota toyota daihatu mitubishia/;
my @uniq = uniq @cars;

print Dumper \@uniq;

ちなみにuniq関数の内部実装を見てみるとなかなか面白いです。grepの代わりにmapを使って実現してます。

# List::MoreUtils-0.22

sub uniq (@) {
    my %h;
    map { $h{$_}++ == 0 ? $_ : () } @_;
}

まぁやってることはgrep版と殆ど同じなんですが、mapで要素除去のテクニックを使ってるあたりがニクイですよね。