- ベストアンサー
配列やハッシュで中身が同じか簡単に調べることは可能でしょうか?
スカラ型なら my $a = "a"; my $b = "b"; if( $a eq $b)の用に比較が簡単に出来ますが、 配列やハッシュはどのように中身が同じかどうか調べることは可能でしょうか? 配列でも複雑な(例えば配列のデータがハッシュ値)のような以下の ものを中身が同じが比較する方法です。 固定でなく、どんなデータが入ってきても数やキーが異なっても比較する方法が知りたいです。 my @ary1 = (); $ary[0]{'test_a'} = "a"; $ary[0]{'test_b'} = "b"; $ary[1]{'test_a'} = "aa"; $ary[1]{'test_b'} = "bb"; my @ary2 = (); $ary[0]{'test_a'} = "aa"; $ary[0]{'test_b'} = "bb"; $ary[1]{'test_a'} = "aaa"; $ary[1]{'test_b'} = "bbb";
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
Test::Deepのeq_deeply()が簡単で使いやすいです。 ハッシュでも、配列でも何でも比較できるみたいです。例題であれば↓ use Test::Deep; my @ary1 = (); $ary1[0]{'test_a'} = "a"; $ary1[0]{'test_b'} = "b"; $ary1[1]{'test_a'} = "aa"; $ary1[1]{'test_b'} = "bb"; my @ary2 = (); $ary2[0]{'test_a'} = "aa"; $ary2[0]{'test_b'} = "bb"; $ary2[1]{'test_a'} = "aaa"; $ary2[1]{'test_b'} = "bbb"; if(eq_deeply( \@ary1, \@ary2, 'Compare array' )){ print "Same structure\n"; }else{ print "Different structure\n"; }
その他の回答 (5)
- kabaokaba
- ベストアンサー率51% (724/1416)
とりあえず,「中身を見る」のが先決だと思うので, Data::Dumper を使うというのはどうでしょうか. Dumperで文字列にして それを「文字列として」比較しています. Test系のモジュールに この手の比較に特化したものがあるかもしれませんね use strict; use warnings; use Data::Dumper; my @ary1 = ( {'test_b' => "b"}, {'test_a' => "aa"}, {'test_b' => "bb"}, ); my @ary2 = ( {'test_b' => "c"}, {'test_a' => "aa"}, {'test_b' => "bb"}, ); if (Dumper(@ary1) eq Dumper(@ary2)){ print "EQ"; }else{ print "NOT EQ"; }
- Tacosan
- ベストアンサー率23% (3656/15482)
あ, 言い忘れてた. 「中身が複雑」だとすると, 「同じ」かどうかの判定から考えないとダメですね. 例えば, $a = [ 1 ]; $b = [ 1 ]; としたときに, $a と $b は「別のリファレンス」だけど「同じデータを持つ配列」のリファレンスではあるわけで, このときに「同じ」とするか「違う」とするかという問題があります. もっとも, 「中身が複雑」で「簡単にチェック」は矛盾してるような気がするなぁ....
- Tacosan
- ベストアンサー率23% (3656/15482)
ん~, それぞれのデータ型に応じて適切に比較するサブルーチンを作り, 再帰的にチェックするしかないんじゃないかなぁ? 例えば, 配列だと sub check_array($$) { my ($array1, $array2) = @_; return 0 if $#$array1 != $#$array2; for my $i (0 .. $#$array1) { my $type1 = ref $array1->[$i]; my $type2 = ref $array2->[$i]; return 0 if $type1 ne $type2; return 0 if ! $check{$type1}->($array1->[$i], $array2->[$i]); } 1; } みたいな. あ, %check は %check = ( SCALAR => \&check_scalar, ARRAY => \&check_array, ...); みたいにデータ型に対して比較ルーチンを記憶しておくハッシュです.
- kumoz
- ベストアンサー率64% (120/185)
単純にループを積み重ねただけです。 foreach my $index_1 (0 .. $#ary1) { foreach my $key_1 (keys %{$ary1[$index_1]}) { foreach my $index_2 (0 .. $#ary2) { foreach my $key_2 (keys %{$ary2[$index_2]}) { if ($ary1[$index_1]->{$key_1} eq $ary2[$index_2]->{$key_2}) { ... } # 値のみ同じ # if ($key_1 eq $key_2 && $ary1[$index_1]->{$key_1} eq $ary2[$index_2]->{$key_2}) { ... } # キーと値が同じ } } } }
- pipipi523
- ベストアンサー率40% (148/365)
@ary1と@ary2の比較ならそれなりの処理が必要です >固定でなくどんなデータが入ってきても数やキーが異なっても比較する方法 例えにある配列を比較するならこんな感じでしょうか・・・ ※素人なのでスマートでカッコイイのは書けませんm(_ _;m my @ary1 = (); $ary1[0]{'test_a'} = "a"; $ary1[0]{'test_b'} = "b"; $ary1[1]{'test_a'} = "aa"; $ary1[1]{'test_b'} = "bb"; my @ary2 = (); $ary2[0]{'test_a'} = "a"; $ary2[0]{'test_b'} = "bb"; $ary2[1]{'test_a'} = "aaa"; $ary2[1]{'test_b'} = "bbb"; if($#ary1 != $#ary2){ print "配列の数が異なる\n"; }else{ for($i=0;$i<=$#ary1;$i++){ if(join(",",sort keys(%{$ary1[$i]})) ne join(",",sort keys(%{$ary2[$i]}))){ print "\$ary1[$i]と\$ary2[$i]には異なるキーが存在\n"; }else{ foreach $key (sort keys(%{$ary1[$i]})){ if($ary1[$i]{$key} ne $ary2[$i]{$key}){ print "\$ary1[$i]{'$key'}と\$ary2[$i]{'$key'}は不一致\n"; }else{ print "\$ary1[$i]{'$key'}と\$ary2[$i]{'$key'}は一致\n"; } } } } }