アプリ版:「スタンプのみでお礼する」機能のリリースについて

aaa.txt
06011800, 5.3
06012100, 5
06020000, 4.5
06020300, 6.2


bbb.txt
06011800, 5.1
06012100, 7.5
06020000, 5.1
06020300, 9.3


という二つのファイルがあります。
以下のプログラムを用いて、
06011800, 5.3, 5.1
06012100, 5, 7.5
06020000, 4.5, 5.1
06020300, 6.2, 9.3

といった感じでデータを作る事に成功したのですが、どうしてもループに無駄が多く、時間がかかってしまいます。
連想配列などを使えば時間が短縮出来そうなのですが、よくわかりません。
ご教示いただけないでしょうか。


以下、作成したプログラム。
$csvfile1 = $ARGV[0];
$csvfile2 = $ARGV[1];

open(DAT1, $csvfile1) || die $!;
while($line=<DAT1>) {
chomp($line);
@dat = split(/,/,$line);

open(DAT2, $csvfile2) || die $!;
while($line2=<DAT2>) {
chomp($line2);
@dat2 = split(/,/,$line2);

if($dat[0] == $dat2[0]){
print "$dat[0],$dat[1],$dat2[1]\n";
}
}
}

close(DAT);

A 回答 (5件)

あなたがつくられたスクリプトをできるだけ生かすようにして連想配列を


つかったスクリプトを作成しました。
いかのようになります。
-------------------------------------------------------------
$csvfile1 = $ARGV[0];
$csvfile2 = $ARGV[1];
#$csvfile1全体を一気に読み込む
open(DAT1, $csvfile1) || die $!;
@lines1=<DAT1>;
close (DAT1);

#$csvfile2全体を一気に読み込む
open(DAT2, $csvfile2) || die $!;
@lines2=<DAT2>;
close (DAT2);

#$csvfile1から連想配列を作る
foreach $line (@lines1){
chomp $line;
@data = split(/,/,$line);
$hash1{$data[0]} = $data[1];
}

#$csvfile2から連想配列を作る
foreach $line (@lines2){
chomp $line;
@data = split(/,/,$line);
$hash2{$data[0]} = $data[1];
}

#以下$csvfile1のデータを元にして出力する処理
#$csvfile1の連想配列のキーだけを取り出す、そしてソートする
@key1 = sort(keys(%hash1));

#取り出したキーを1つずつ処理する
foreach $key (@key1){
#第1列目のデータが$csvfile1,$csvfile2の両方に存在するものだけ出力する
if (exists($hash2{$key})){
print $key,",",$hash1{$key},",",$hash2{$key},"\n";
}
}

-------------------------------------------------------------
尚、第1列目のデータが両方のファイルにあるものだけを出力しています。
例えば、aaa.txtの1行目
06011800, 5.3
の06011800がbbb.txtに無い場合は、そのデータは出力しません。
(逆のケースも同様です)
    • good
    • 0
この回答へのお礼

解決しました!ありがとうございました。

お礼日時:2014/08/15 17:01

push は autovivification が効くので


$ret->{$d[0]} = [$d[1]];
の代わりに
push @{$ret->{$d[0]}, $d[1];
とできますな>#4.

結果として 2つの while ループはほぼ同一の形になったりする.
    • good
    • 0
この回答へのお礼

ありがとうございました!

お礼日時:2014/08/15 17:03

Unix コマンドなら、


join -t, aaa.txt bbb.txt
と、この処理に適したコマンドが既に存在しています。

両方のレコードにあるものを出力するとすると、
例えば、こんな感じでしょうか。
http://pastebin.com/xz9dPGXy

片方だけのものを出力して良いなら、
while (<$csv2>) {...}
の中の else 側の処理をコメントにします。さらに、出力部分の、next の行をコメントにします。
    • good
    • 0
この回答へのお礼

ありがとうございました!

お礼日時:2014/08/15 17:03

OSは何ですか?UNIX系でよいですか。


2つのファイルの1列目が同じ時だけ出力すれば良いのなら、

sort aaa.txt bbb.txt |gawk -F, '{if($1=time){print time, dat, $2};time=$1;dat=$2}'

Perlがよければ上の行をPerlのsystem関数で実行してください。
    • good
    • 0
この回答へのお礼

ありがとうございました。便利なコマンドですね。

お礼日時:2014/08/15 17:04

「連想配列などを使えば時間が短縮出来そうなのですが、よくわかりません」ってのは, 具体的には何がどう「よくわからない」んでしょうか?



一方にあって他方にはないデータをどうするかなど詰めるべき点はあるけど, 配列のハッシュなりハッシュのハッシュなりを使えばいいだけですよね.
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2014/08/15 17:04

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