dポイントプレゼントキャンペーン実施中!

高速に文字列の比較

open(IN,"$file");
while (<IN>) {
my($ip,$flag) = split(/,/,$_);
if($flag==1){$data .= "$ip,";}
}
close(IN);

open(IN,"$file2");
while (<IN>) {
my($ip,$x,$z) = split(/,/,$_);
foreach ( split(/,/, $data) ) {
if ($ip eq $_) {$xdata.= "$ip,$x,$z\n";}
}
close(IN);


1.$fileで、$flagが1なら$ipを変数$dataに加えます。
2.$file2の$ipが、$dataの$ipに含まれていれば,$file2のデーターを$xdataに加えます。

上記の書き方で一応比較は出来ているようなのですが、perlの知識があまりない素人が適当に考えた書き方なので、自信がありません。
$data .= "$ip,";の$ipの後ろに,を入れている部分も何だか変なのですが、他の書き方が思いつけません。

書き方が間違っている場合や、こうすればもっと高速に動作させられるという書き方があれば、ご指導いただけると幸いです。
$fileも$file2も、100万行あたりまで増える見込みなので、出来るだけサーバーに負荷のかからない書き方ができればと思っています。
お手数ですが、どうぞよろしくお願いいたします。

A 回答 (3件)

一応「配列なりハッシュなり」と書いたんだけど, 「たくさんの文字列と等しいかどうか比較する」ときには戦略の 1つとして「比較対象となる文字列をキーに持つハッシュを使う」ことがあります. たとえば, 前半のループを


while (<IN>) {
my($ip,$flag) = split(/,/,$_);
if ($flag == 1) { $data{$ip} = 1; }
}
として, 比較対象の文字列をハッシュ %data のキーに入れます. すると後半は
while (<IN>) {
my($ip,$x,$z) = split(/,/,$_);
if (defined $data{$ip}) {$xdata.= "$ip,$x,$z\n";}
}
とでき, foreach ループをまるまる消し去ることができてしまいます.
この辺はメモリとのトレードオフにもなるので, 何を優先するかによってどうするかが決まります.
ちなみに前半のループで文字列を配列 @data に入れたときは, 後半のループ中
foreach ( split(/,/, $data) )
のところが
foreach (@data)
のようになります.
ところで, 最終的に $xdata をどうするの? これも, 場合によっては配列にする方がいいかも.
    • good
    • 0
この回答へのお礼

有難うございます。
ループが減る分、かなりサーバー負荷が抑えられそうです。
ハッシュキーに入れてdefinedを使うのも大変勉強になりました。
$xdataは、この後エンコードしてから使うのですが、配列に入れられるかどうかも
試してみようと思います。
はやり自分では想像もつかないような方法がいろいろとあるものなのですね。
perlの魅力が益々深まりました。感謝感激です。

お礼日時:2010/09/04 00:42

なんで配列なりハッシュなりを使おうとしないんだろう.


あと, 本当に速度を気にするならデータベースの使用も視野に入れたいところ.

この回答への補足

foreach (@data) {
if ($ip eq $_) {$xdata.= "$ip,$x,$z\n";}
}
申し訳ありません。勘違いしていたようです。
出来ました。
ファイルの比較は、いろいろ考えていたところ、
改良案が思いついたので、
$fileの$data .= "$ip,";は、1000行分で、
$file2はファイルが10万行以内で収まりそうです。
あと、教えていただいたデータベースの使い方も勉強してみようと思いますが、
質問にある書き方より、本来はこうやって書くほうがいいよという
サンプルコード等があれば、参考のため、よろしくお願いいたします。

補足日時:2010/09/03 21:10
    • good
    • 0
この回答へのお礼

有難うございます。
push(@data, "$xid");
配列はこんな感じでいいのでしょうか?
この場合、以下の箇所をどのように書き直すのがいいのかわかりませんでした。
初歩的な質問で申し訳ないのですが、よろしくお願いいたします。
foreach ( split(/,/, $data) ) {
if ($ip eq $_) {$xdata.= "$ip,$x,$z\n";}
}

お礼日時:2010/09/03 20:32

そもそも、百万件近くのデータ処理を行うのでしたら、


最小からコンパイラ言語を使った方が、よほど負荷が
軽くなるはずです。
    • good
    • 0
この回答へのお礼

ご意見有難うございます。
プログラミングは一番初めにC言語を勉強し始めたのですが、
まったくわけわからず、断念しました。
perlは簡単な改造の方法を掲載してくれているサイトを参考に
少しずつ覚えている程度です。
なので、現時点では他の言語を覚える余裕がありません。
将来的にはいろいろな言語に手をだしてみたいと思っているのですが、
自分の頭では無理かも…。

あと、ファイル桁数は、将来的に増えた場合の目安なので、
当分の間は桁数が増えることはないと思います。
もしサーバーに負荷がかかるようになってきたら、専用サーバーなども検討する
予定ですが、現時点では小規模運営なので、出来るだけ負荷のかからない
書き方を勉強できたらと思います。
試行錯誤の末、質問にある比較コードを書いたのですが、
おかしなところがあれば指摘してもらいたいのと、
もっと正しい書き方があれば、そういった書き方を覚えたいという思いから
質問させていただきました。どうぞよろしくお願いいたします。

お礼日時:2010/09/03 18:03

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!