小池啓仁 ヒロヒト応援ブログ By はてな

小池啓仁(コイケヒロヒト)の動画など。

小池啓仁 ヒロヒト応援ブログ By はてな

配列の代入と比較

Perlでの配列変数同士の代入は普通に出来ます。
代入先配列と代入元配列の関係は、代入すると代入先配列は代入元配列とイコールになります。
つまり、要素数も要素の並びも同じになりますね。

use strict;
use warnings;

local $, = ' ';
my @aaa = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
my @bbb = ('a', 'b', 'c', 'd', 'e');

@aaa = @bbb;
print @aaa;


一方、比較は普通にはできません。たとえば、以下はイコールになってしまいます。

my @bbb = ('a', 'b', 'c', 'd', 'e');
my @ccc = ('x', 'b', 'c', 'd', 'e');

if (@aaa == @ccc) {
    print "イコール\n";
}
else {
    print "ノットイコール\n";
}

これは、単に要素数の比較なって、上記は、たまたま要素数が同じなのでイコールになるのです。
つまり、配列同士の比較は、意外と難しいのです。
正攻法では、要素をループで比較すればいいですね。たとえば、以下の感じ。

if (ArrayCmp(\@aaa, \@ccc)) {
    print "イコール\n";
}
else {
    print "ノットイコール\n";
}

sub ArrayCmp {
my ($a, $b) = @_;
    # 要素数は同じか?
    return 0 if @$a != @$b;
    # 要素値は同じか?
    for (0..$#$a) {
         return 0 if $a->[$_] ne $b->[$_];
    }
    return 1;
}

しかし、比較するのにわざわざsubするのもアレなので、なにか良い方法がないかとググルとありました。

@deff = grep { !{map{$_,1}@array2 }-> {$_}}@array1;
perlで2つの配列を比較する方法について - あなたの疑問をみんなで解決 まぐまぐ!Q&A

これは、すばらしい!
grep、map、無名ハッシュの組み合わせが絶妙ですね。
ポイントは、mapで@array2を元にハッシュを作成して、それを中カッコで無名ハッシュリファレンスにして、そのハッシュのキーにgrepで@array1からもってくる…。
これが理解できれば、Perl初心者は卒業ですね。
分かりやすい解説が引用先に書いてありましたよ。


ちなみに、上記の@deffには、@array2と@array1がイコールだと偽が返り、ノットイコールだと一致しなかった要素値が返ります。


本ブログの応援クリック も、よろしくお願い致します。