高速に文字列の比較
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万行あたりまで増える見込みなので、出来るだけサーバーに負荷のかからない書き方ができればと思っています。
お手数ですが、どうぞよろしくお願いいたします。
No.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 をどうするの? これも, 場合によっては配列にする方がいいかも.
有難うございます。
ループが減る分、かなりサーバー負荷が抑えられそうです。
ハッシュキーに入れてdefinedを使うのも大変勉強になりました。
$xdataは、この後エンコードしてから使うのですが、配列に入れられるかどうかも
試してみようと思います。
はやり自分では想像もつかないような方法がいろいろとあるものなのですね。
perlの魅力が益々深まりました。感謝感激です。
No.2
- 回答日時:
なんで配列なりハッシュなりを使おうとしないんだろう.
あと, 本当に速度を気にするならデータベースの使用も視野に入れたいところ.
この回答への補足
foreach (@data) {
if ($ip eq $_) {$xdata.= "$ip,$x,$z\n";}
}
申し訳ありません。勘違いしていたようです。
出来ました。
ファイルの比較は、いろいろ考えていたところ、
改良案が思いついたので、
$fileの$data .= "$ip,";は、1000行分で、
$file2はファイルが10万行以内で収まりそうです。
あと、教えていただいたデータベースの使い方も勉強してみようと思いますが、
質問にある書き方より、本来はこうやって書くほうがいいよという
サンプルコード等があれば、参考のため、よろしくお願いいたします。
有難うございます。
push(@data, "$xid");
配列はこんな感じでいいのでしょうか?
この場合、以下の箇所をどのように書き直すのがいいのかわかりませんでした。
初歩的な質問で申し訳ないのですが、よろしくお願いいたします。
foreach ( split(/,/, $data) ) {
if ($ip eq $_) {$xdata.= "$ip,$x,$z\n";}
}
No.1
- 回答日時:
そもそも、百万件近くのデータ処理を行うのでしたら、
最小からコンパイラ言語を使った方が、よほど負荷が
軽くなるはずです。
ご意見有難うございます。
プログラミングは一番初めにC言語を勉強し始めたのですが、
まったくわけわからず、断念しました。
perlは簡単な改造の方法を掲載してくれているサイトを参考に
少しずつ覚えている程度です。
なので、現時点では他の言語を覚える余裕がありません。
将来的にはいろいろな言語に手をだしてみたいと思っているのですが、
自分の頭では無理かも…。
あと、ファイル桁数は、将来的に増えた場合の目安なので、
当分の間は桁数が増えることはないと思います。
もしサーバーに負荷がかかるようになってきたら、専用サーバーなども検討する
予定ですが、現時点では小規模運営なので、出来るだけ負荷のかからない
書き方を勉強できたらと思います。
試行錯誤の末、質問にある比較コードを書いたのですが、
おかしなところがあれば指摘してもらいたいのと、
もっと正しい書き方があれば、そういった書き方を覚えたいという思いから
質問させていただきました。どうぞよろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) pythonのこのエラーがわかりません 3 2022/11/16 14:54
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- その他(プログラミング・Web制作) python flask から fastapiへの移行時のエラー対処 1 2023/02/05 12:26
- その他(プログラミング・Web制作) python 2 2022/12/23 09:06
- PHP if(preg_match("/[^0-9]/",$gu_d)){意味を教えてください。 1 2022/05/06 05:37
- PHP htmlspecialcharsが機能していないです。 バグですか? 1 2022/04/05 01:22
- 固定IP iPhoneでのIPv4切り替え方法 3 2022/11/24 22:26
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- Excel(エクセル) SUMIFSと日付変換 10 2023/04/16 15:38
- Ruby パイソンエラーについて 1 2022/12/24 14:07
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
HTML::TemplateのTMPL_LOOPにつ...
-
VBのReturnの使い方
-
画面を強制的に再描画させる方法
-
範囲指定したセルを1つずつ飛...
-
VBAで3秒だけ時間を止めたい
-
VBAでの一時停止と再開の方法
-
DoEventsが必要な理由について
-
vbscriptでIE自動入力(途中で...
-
データベースから取得したデー...
-
DOSコマンドのループ内のTIMEコ...
-
Escキーを押すと、中断する時と...
-
流れ図(フローチャート)が分か...
-
ハッシュマーク以降のアドレス取得
-
再帰関数のインライン展開
-
Excel vba でコンボボックスの...
-
リストボックスに縦スクロール...
-
UWSCに制限時間を付けたいです
-
vb.netです。2次元配列の要素を...
-
forループは何故、forなのですか?
-
Perlのサブルーチンの引数に配...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語について。
-
高速に文字列の比較
-
VB6の公式リファレンスはありま...
-
連番ごとに印をつける
-
HTML::Templateのループと配列...
-
双方向リスト(?)
-
HTML::TemplateのTMPL_LOOPにつ...
-
プログラミングについて。 1つ...
-
画面を強制的に再描画させる方法
-
VBのReturnの使い方
-
どなたかこのプログラミングを...
-
VBAでの一時停止と再開の方法
-
VBA for i=1 to lastrow
-
UWSCの終了の仕方
-
DoEventsが必要な理由について
-
エクセルの当番表を作っていま...
-
VBAで3秒だけ時間を止めたい
-
ハッシュ検索はなぜ速い
-
GIFアニメをループさせたくない
-
Escキーを押すと、中断する時と...
おすすめ情報