データ処理に関する質問です.皆さんの手助けのおかげで,以下のような二つのファイルを作ることができました.


a_1.txt(各テストの得点.例えばtest1の"1→3"はtest1の1問目が3点だったことを表す)

test1
1→3
2→2
3→2
4→5

test2
1→2
2→3
3→2
4→3
3→3


a_2.csv(a_1の点数にそれぞれ対応している)

id=test2=,8,2,5,6,1,
id=test1=,4,2,1,4,

この2つから新しい3つめのファイルを作ろうと思っています.
まずa_2.csvの8,2,5,6,1,4,2,1,4の平均を求めます.この場合は3.66です.これよりa_2のデータの数字が大きい場合は得点を2倍にして,小さい場合は半分にして,新たな得点を出力させたいです.
例えば,test1の1の得点は3点ですが,a_2を見ると4が対応していて,これは3.66より大きいので2倍になり,
1→6
と出力させたいです.

全体として,a_1と同じような形式にして保存したいと思っています.
かなりの数のデータがあるので,Perlで処理するのがいいと思ってるんですけど手を貸していただけたら嬉しいです.

回答の条件
  • 1人3回まで
  • 登録:2007/12/12 22:16:59
  • 終了:2007/12/14 17:11:36

ベストアンサー

id:imo758 No.1

imo758回答回数121ベストアンサー獲得回数192007/12/13 01:30:42

ポイント35pt

こういうことかな?合ってるか自信ないですが。運用は自己責任でよろしく。

open A_1, "<a_1.txt" or die "A_1 open error";
while(<A_1>){
	if(/^(\d+)[^\d]+(\d+)$/){
		${$a_1{$id}}[$1] = $2;
	}else{
		chomp;
		$id = $_;
	}
}
close A_1;

open A_2,"<a_2.csv" or die "A_2 open error";
while(<A_2>){
	/^id=(test\d+)=([\d\,]+)$/ or die "error A_2 matching";
	($id, $points) = ($1, $2);
	@{$a_2{$id}} = (split /,/, $points);
	$num += $#{$a_2{$id}};
	map{$sum += $_;} @{$a_2{$id}};
}
close A_2;
$avarage = $sum / $num;

foreach$id(keys %a_1){
	print "$id\n";
	for($i=1; $i<=$#{$a_1{$id}}; $i++){
		$point1 = ${$a_1{$id}}[$i];
		$point2 = ${$a_2{$id}}[$i];
		printf "$i→%d\n", (($avarage < $point2) ? $point1*2 : ($avarage == $point2 ? $point1 : $point1/2));
	}
}
id:ishikennn

ちゃんと動きました!ありがとうございます.

test1とかtest2以外に,例えばanswer1とかanswer2とかがあったとすると,正規表現の/^id=(test\d+)=([\d\,]+)$/のあとにor /^id=(answer\d+)=([\d\,]+)$/を追加すればいいんですかね?

2007/12/13 07:10:59

その他の回答(1件)

id:imo758 No.1

imo758回答回数121ベストアンサー獲得回数192007/12/13 01:30:42ここでベストアンサー

ポイント35pt

こういうことかな?合ってるか自信ないですが。運用は自己責任でよろしく。

open A_1, "<a_1.txt" or die "A_1 open error";
while(<A_1>){
	if(/^(\d+)[^\d]+(\d+)$/){
		${$a_1{$id}}[$1] = $2;
	}else{
		chomp;
		$id = $_;
	}
}
close A_1;

open A_2,"<a_2.csv" or die "A_2 open error";
while(<A_2>){
	/^id=(test\d+)=([\d\,]+)$/ or die "error A_2 matching";
	($id, $points) = ($1, $2);
	@{$a_2{$id}} = (split /,/, $points);
	$num += $#{$a_2{$id}};
	map{$sum += $_;} @{$a_2{$id}};
}
close A_2;
$avarage = $sum / $num;

foreach$id(keys %a_1){
	print "$id\n";
	for($i=1; $i<=$#{$a_1{$id}}; $i++){
		$point1 = ${$a_1{$id}}[$i];
		$point2 = ${$a_2{$id}}[$i];
		printf "$i→%d\n", (($avarage < $point2) ? $point1*2 : ($avarage == $point2 ? $point1 : $point1/2));
	}
}
id:ishikennn

ちゃんと動きました!ありがとうございます.

test1とかtest2以外に,例えばanswer1とかanswer2とかがあったとすると,正規表現の/^id=(test\d+)=([\d\,]+)$/のあとにor /^id=(answer\d+)=([\d\,]+)$/を追加すればいいんですかね?

2007/12/13 07:10:59
id:imo758 No.2

imo758回答回数121ベストアンサー獲得回数192007/12/13 08:12:08

ポイント35pt

汎用性損ねてすいません。それならいっそのこと

/^id=(test\d+)=([\d\,]+)$/

ではなく

/^id=(\w+\d+)=([\d\,]+)$/

のほうがいいかもしれません

id:ishikennn

正規表現でそういうことも表現できるんですね.便利です.

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

2007/12/14 17:04:15

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません