たとえば配列が2つ有って、その中で重複する値を知りたいとする。

片方は別に配列でなくてもいいのだが(ディレクトリハンドルが読み出すファイルのリスト等でもいい)要はその値が他方の配列の中に存在するかどうかを知りたいというのはよくある。
例えばRubyだとinclude?というメソッドがあるしPythonの場合in演算子というのが使える。
それぞれコードは

#!/usr/bin/env ruby

names1 = ["taro", "hanako", "ichiro", "yoko", "shingo"]
names2 = ["sachiko", "shingo", "takuya", "toshihiko", "yoko"]

names1.each do |i|
    puts i if names2.include?(i)
end

と、

#!/usr/bin/env python

names1 = ["taro", "hanako", "ichiro", "yoko", "shingo"]
names2 = ["sachiko", "shingo", "takuya", "toshihiko", "yoko"]

for i in names1:
    if i in names2: print i

とまあ、こんな感じでそれぞれは

yoko
shingo

と出力される。

すごく分かりやすいがPerlの場合はどう書けばいいのだろう?
もちろんサブルーチンを書いてしまえば何の問題もないが、もっと簡単に書けないものかなあ・・とふと今日思ってしまった。

いろいろ試行錯誤した結果こんなコードになった。

#!/usr/bin/env perl

use strict;
use warnings;

my @names1 = ("taro", "hanako", "ichiro", "yoko", "shingo");
my @names2 = ("sachiko", "shingo", "takuya", "toshihiko", "yoko");

print join("\n", grep{ sub{ for my $tmp (@names2) { return 1 if ($tmp eq $_) } }->() } @names1);

これでとりあえず上の目的は達成できたが、この場合"存在する要素"を目的としているのでうまくいくが、逆に"存在しない要素"を出力したい時は全然うまく行かない。
ifをunlessに変えたりeqをneにしたりしても駄目

RubyやPythonの場合は

names1.each do |i|
    puts i unless names2.include?(i)
end

for i in names1:
    if not i in names2: print i

こうするだけでうまく行くんだがなあ。

それにPerlのコードは一見しただけでは汚くて訳が分からない。
こんなコード書いてちゃ駄目だな。

カテゴリ:

トラックバック(0)

トラックバックURL: http://blog.beanz-net.jp/beanz_mtos/mt-tb.cgi/3

コメントする