ある二つのファイル(moto1.csvとmoto2.csv)の2番目のフィールドが
おなじときに二つのファイルの中身をあわせて別のファイル(kekka.csv)を
作る作業をしています。
下記のソースで※2の場所で何回もファイルをオープンさせるととても重いので
※1でファイルを一回だけオープンさせて処理しようと思ったら。
内側のループ(moto2_Log)が一回しか処理されないので困っております。
何かよいアイデアがありましたらよろしくお願いします。
open(moto1_Log,"< moto1.csv");
open(kekka_Log,"> kekka.csv");
※1open(moto2_Log,"< moto2.csv");
while( <moto1_Log> ) {
chop;
@moto1_List=split(/,/);
※2#open(moto2_Log,"< moto2.csv");
while( <moto2_Log> ) {
chop;
@moto2_List=split(/,/);
if($moto1_[1] eq $moto2_List[1]){
print kekka_Log $S_List[0];
print kekka_Log ",";
print kekka_Log $S_List[1];
print Export_Log ",";
print Export_Log $S_List[2];
print Export_Log ",";
print Export_Log $S_List[3];
print Export_Log ":";
print Export_Log $E_List[0];
print Export_Log ",";
print Export_Log $E_List[1];
print Export_Log ",";
print Export_Log $E_List[2];
print Export_Log ",";
print Export_Log $E_List[3];
print Export_Log "\n";#改行コード
continu;
}
}
}
close (moto2_Log);
close(kekka_Log);
close(moto1_Log);
No.2ベストアンサー
- 回答日時:
原因についてはa-kumaさんが仰ってる通りですので、
代替案を挙げたいと思います。
「何回もファイルをオープンさせるととても重いので」という
ことですが、ファイルを一々巻き戻す(seekする)現在の方法でも、
実行時間としてはほとんど変わらないと思いますよ。
openにかかる時間が中身をリードする時間と比較して、
誤差以上に意味のある時間になるとは思えません。
同様のプログラムをつくって、moto1.csvとmoto2.csvとして
500行のテキストファイル(具体的には500行に切り詰めた
Linuxのシステムログ/var/log/messagesファイル)
を使って実験したところ、
一々オープンする方法の実行時間(47.63秒)は、
巻き戻す方法の実行時間(47.28秒)と比較して、
たった0.7%しか増加しませんでした。
この実験では、moto2.csvは全てキャッシュに乗っていますが、
キャッシュに乗りきらないほど大きなファイルになったとしても、
さして結果は変わらないと思います。
そこで代替案ですが、一旦、片方のファイルを全て
配列に読み込んではどうでしょう?
open(moto2_Log, "<moto2.csv");
my @moto2_List;
while(<moto2_Log>){
chomp;
my @cols = split(/,/);
push(@moto2_List, \@cols);
}
close(moto2_Log);
open(moto1_Log, "<moto1.csv");
open(kekka_Log, ">kekka.csv");
while(<moto1_Log>){
chomp;
my @moto1_List = split(/,/);
foreach $m2lst ( @moto2_List ){
if( $moto1_List[1] eq $m2lst->[1] ){
print kekka_Log ...
}
}
}
close(kekka_Log);
close(moto1_Log);
上の実験と同じ500行のテキストファイルに対して、
この方法だと実行時間は約5分の1の、10.17秒と
なりました。まあ、ファイルアクセスの時間だけ
じゃなくて、splitの回数も減ってるので、その
影響もあるんでしょう。
ところで、このアルゴリズムだと、moto1.csvの
中の各行とmoto2.csvの中の全行を照合してますが、
それはそれで合ってるんでしょうか?
> 2番目のフィールドが
> おなじときに二つのファイルの中身をあわせて別のファイル(kekka.csv)を
> 作る
という辺りから、moto1.csvの各行と、moto2.csvで
対応する(ファイルの先頭から数えた行数が同じ)行を
照合することを意図しているようにも読めるんですが…。
ありがとうございます。
確かに時間はさほど変わりませんでした。
どうやって時間を短縮さえ酔うと悩んでいたところです。
とても参考になります。
No.3
- 回答日時:
2件の回答がついていますが、解決はされたのでしょうか?
質問に書かれたソースと、全く同じ動作をするコードを書いてみました。参考にしてみてください。
my %moto2;
open IN, 'moto2.csv';
while (<IN>) {
chomp;
my $_2nd = (split(/,/))[1];
$moto2{$_2nd} = $_ unless defined $moto2{$_2nd};
}
close IN;
open OUT, '>kekka.csv';
open IN, 'moto1.csv';
while (<IN>) {
chomp;
my $_2nd = (split(/,/))[1];
print OUT "$_, $moto2{$_2nd}\n" if defined $moto2{$_2nd};
}
close IN;
close OUT;
○moto2.csvの2番目のデータをキーにしたハッシュを作成します。
値はそのデータの行全体(改行は抜いたもの)にします。後で結局カンマ区切りの合成をするので、そのまま使うわけです。
○moto1.csvを開いて1行ずつ読み、2番目のデータを取り出します。
このデータを%moto2のKEYにして値があれば、moto1とmoto2で全く同じデータが存在するわけです。
○kekka.csvには、2番目に同じデータがある行の全項目をカンマ区切りにしたデータを入れるので、split前のデータから改行を抜いたもの同士をカンマを挟んで書き込みます。
(%moto2のVALUEには、moto2.csvから改行を抜いたデータが入れてある)
No.1
- 回答日時:
二つ目のファイルを一回読み込んだら、読み込み位置がファイルの一番お尻に
あるからですね。
二つ目のファイルを処理しおわったら、巻き戻しましょう。
open(moto1_Log, ...);
open(moto2_Log, ...);
while ( <moto1_Log> ) {
...
while ( <moto2_Log> ) {
...
}
seek(moto2_Log, 0, 0); # ← これ
}
ってな感じ。
# perl は良く知らないんですけど、多分OK
seekですね
理由は何と無く分かったいました。
戻し方が解りませんでした(リファレンスだけだと探すのが大変です)
ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 数学 log底10真数1/75 ただし、 log底10真数2=0.3 log底10真数3=0.5とする 式 2 2022/05/30 22:51
- タブレット log撮影で撮った写真について。 こんにちはカメラ初心者です、わたしは今までほとんどの写真をlog撮 3 2023/07/04 01:42
- 数学 微分方程式の積分定数について 5 2023/07/13 08:39
- その他(プログラミング・Web制作) pythonのmap、結果の利用は1度だけ? 5 2022/06/11 12:33
- その他(プログラミング・Web制作) python 3.10で 同じlistに同じ構文で同じデータ代入した結果が異なる現象発生 7 2022/06/18 11:08
- 数学 n乗はどうなったのでしょうか 1 2023/01/31 19:26
- 数学 写真の数学の質問です。 常用対数ってのがいまいちわかりません。 log(10)3が、なぜlog(10 5 2023/06/10 14:07
- 数学 回答者どもがなかなか答えられないようなので、考えてみました。 ∫[0,π/2]log(sinx)/( 4 2022/08/31 16:30
- PHP if(preg_match("/[^0-9]/",$gu_d)){意味を教えてください。 1 2022/05/06 05:37
- 数学 O(N*logN)よりN=8の時、 O(N*logN) のOはオーダー記号と推察されますから 8*l 6 2022/04/06 18:54
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Perlで特定行から特定行までを...
-
MATLAB std::exceptionエラー
-
batファイルでrenameができませ...
-
ExcelをCSV書き出す場合のシー...
-
バッチファイルの作り方(CSV→...
-
VBAでCSVファイルの特定行を書...
-
fopenでディレクトリ内の全ファ...
-
VBAで巨大なファイルの途中から...
-
awkスクリプトでダブルクォーテ...
-
ファイル名を複数個配列で確保...
-
VBAでCSVファイルを途中行まで...
-
Perl:Unicodeプロパティ作れない
-
同じようなソースなのですが片...
-
エクセルVBAで素数だけを出力す...
-
【C++/CLI】ファイルオープンに...
-
close()で例外が投げられる理由
-
openした後、closeしないでプロ...
-
Javaのコーディングスタイル
-
重複するデータを抽出できる秀...
-
python renameについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Perlで特定行から特定行までを...
-
Perlの初心者です。2重ループ...
-
perlでcsvファイルを読む(ダブ...
-
Argument "\\\\n" isn't numeri...
-
Java CSVファイルをカンマごと...
-
perlにてスペースの削除に苦労...
-
Perl初心者です。同一データを...
-
ファイルの3行目までを出力したい
-
先頭の単語が一致した時のデー...
-
FTP接続時失敗時、接続先名をcs...
-
データファイルからのデータの...
-
MATLAB std::exceptionエラー
-
cgiのログの書き方
-
エラーチェック、ファイルに特...
-
CSVファイルのデータの行数を取...
-
perlでファイルの比較
-
perl:パターンマッチを使ったif...
-
コマンド上の行間
-
外部ファイルからの指定行と指...
-
CSVファイルをperlプログラムで...
おすすめ情報