- ベストアンサー
二つの配列から、同じ値のもの以外を他の配列に入れたい。
二つの配列から、同じ値のもの以外を他の配列に入れたい。 @tmp = ('1','2','3','4','5'); @tmp2 = ('1','3'); ↓ @tmp3 = ('2','4','5'); 重複を除くの方法はあったのですが、 この場合は、逆の結果が欲しいです。 上記のような結果が欲しいのですが、 うまくできませんでした。 どなたかご伝授いただけないでしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
@wk { @tmp } = (); #tmpの要素でハッシュを作る delete @wk { @tmp2 }; #tmp2の要素を削除する @tmp3 = keys %wk;
その他の回答 (3)
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
#3の方のご指摘の通りです。勘違いした回答をしてしまいました。 回答はでてますけど、書いときます。 for $x (@tmp, @tmp2) { $count{ $x }++; } #要素をカウントする、元の配列自体に重複する要素があるとダメ for $x (keys %count){ push @tmp3,$x if $count{$x} == 1 }
お礼
今回は、NO.1の回答で、できました。 他の場合の処理も考えていただいて、 連想配列の勉強もしないといけないな と思いました。有難うございました。
- leaz024
- ベストアンサー率75% (398/526)
質問の例では、@tmp2 の要素が全て @tmp に含まれているので No.1、2 の回答でも問題ありませんが、命題からすると、@tmp2 にのみ存在する要素があった場合には、それも @tmp3 に入れなければならないように思いますがどうでしょうか?(No.1、2 では入りません。) 下記のスクリプトはその点も考慮してありますが、「@tmp2 だけに存在する要素などない」という場合は、No.1 や 2 の回答の方が効率がよいです。 %check = (); # 重複チェック用ハッシュを初期化 @tmp3 = grep !--$check{$_}, grep !$check{$_}++, @tmp, @tmp2; 多用する場合は関数化するとよいでしょう。 sub list_xor { my %check; grep !--$check{$_}, grep !$check{$_}++, @_; } @tmp3 = list_xor(@tmp, @tmp2); ※スクリプトをコピーする場合は、全角空白をタブなどに置換して下さい。
お礼
失礼しました。 %check = (); にせず、@check=();として いました。 回答有難うございました。
補足
回答有難うございます。今回は、 @tmp2 にのみ存在する要素があった場合の処理は、 必要ではなかったので、NO1さんの回答で うまくできました。このような @tmp2 にのみ存在する時の処理も学べて、 嬉しかったです。有難うございました。 良かったら、1つ回答していただきたいのですが、 for($a=0; $a<2; $a++){ %wk = (); # 重複チェック用ハッシュを初期化 } したところ、うまく削除できず、 おかしな値になりました。 何がいけないのでしょうか? 今は、 for($a=0; $a<2; $a++){ %wk = (); # 重複チェック用ハッシュを初期化 %wk1 = (); # 重複チェック用ハッシュを初期化 } 配列を別名にしました。
- t140
- ベストアンサー率39% (59/150)
@del{@tmp2}= (); @tmp3= grep(!exists $del{$_}, @tmp);
お礼
回答有難うございました。 次回はこの方法も使わせていただきます。 色々な方法があるのですね。 勉強になりました。
お礼
回答有難うございました。 今回は、教えていただいた方法で うまくできました。 早い回答だったので、すぐに 解決できました。本当に有難うございました。