配列の代入と比較
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がイコールだと偽が返り、ノットイコールだと一致しなかった要素値が返ります。