こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

Perl 条件付最小値 率

a.txt

1行目・・・
2行目・・・
以下3行目~
,場所A,1:54.7,2,
,場所A,1:52.5,4,
,場所B,1:51.8,2,
,場所A,1:57.1,4,
,場所B,1:51.5,1,
,場所B,1:49.8,1,



100ほど
※,場所,時間,順位,
となっております

text.pl

open(FILE2, "<","a.txt");
flock(FILE3, 1);
@DATA2 = <FILE2>;
close FILE2;

for ($i=3;$i<14;$i++){
$data2 = $DATA2[$i];
chomp($data2);
my ($B01,$B02,$B03,$B04,$B05,$B06) = split(/,/, $data2);

print "$B03\n";
}

まず、ここまでできているのですが、
これで、各列を取得するとこまでできました。

ここから
(1)この時間の中で 場所A or 場所B での最小値を求めたい

(2)場所A or 場所B での順位が3以上の率を求めたい
※場所Aですと、場所Aが3つあり、3位以上が1、3位未満が2なので
 1÷3×100の33.3%

投稿日時 - 2017-10-04 13:20:03

QNo.9382068

困ってます

質問者が選んだベストアンサー

> for ($i=2;$i<=$#DATA2;$i++){
> この部分の$#DATA2 は最終行までということでしょうか?

はい、ここは3行目から最終行まで処理を行うということになります。
配列(@DATA2)の最終要素番号を知りたい時に、$#配列名とするとその値を得ることが出来ます。
配列の要素番号は「0」から始まりますので、今回のように各行を配列要素として取り込む場合で100行あったとすると、最終要素番号は「99」になります。
これを踏まえると、3行目から取得するので、$iの最初の値を「2」としていることが理解できると思います。

> もし、行が2~15行だけ取得したいとき、

この場合は forループの$i値を次のようにすることで取得できます。
for ($i=1;$i<=14;$i++){
あるいは
for ($i=1;$i<15;$i++){
※「<=」ではなく、「<」となっている部分に注目。

投稿日時 - 2017-10-05 11:28:18

お礼

ありがとうございました!
おかげさまでやりたいことができました!

投稿日時 - 2017-10-06 09:39:30

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

泥臭くやると次のような感じでしょうか。

open(FILE2, "a.txt");
flock(FILE2, 1);
@DATA2 = <FILE2>;
close FILE2;

@placeA = ();
@placeB = ();
$rankA = 0;
$rankB = 0;

for ($i=2;$i<=$#DATA2;$i++){
my $data2 = $DATA2[$i];
chomp($data2);
my ($B01,$B02,$B03,$B04,$B05,$B06) = split(/\,/, $data2);
if ($B02 eq "場所A") {
push(@placeA,$B03);
if ($B04 <= 3) { $rankA++; }
}
elsif ($B02 eq "場所B") {
push(@placeB,$B03);
if ($B04 <= 3) { $rankB++; }
}
}

@sortA = sort(@placeA);
print "場所Aの最小値:" . @sortA[0] . "\n";

@sortB = sort(@placeB);
print "場所Bの最小値:" . @sortB[0] . "\n";

$Anum = $#placeA + 1;
$Bnum = $#placeB + 1;

print "場所Aの3位以上の率:";
if ($rankA > 0) {
$ritsuA = ($rankA / $Anum) * 100;
print $ritsuA . "%\n";
}
else { print 0 . "%\n"; }

print "場所Bの3位以上の率:";
if ($rankB > 0) {
$ritsuB = ($rankB / $Bnum) * 100;
print $ritsuB . "%\n";
}
else { print 0 . "%\n"; }

小数点以下を任意の桁数で四捨五入したいのであれば、
Math::Roundモジュールを読み込んで、次のように書き換えればOKです。

$ritsuA = ($rankA / $Anum) * 100;
      ↓
$ritsuA = nearest(0.1, ($rankA / $Anum) * 100); #小数点以下1桁

0.1を0.01にすると小数点以下2桁になります。

投稿日時 - 2017-10-04 21:21:57

お礼

ありがとうございます!
ほしい値を取得することができました!

for ($i=2;$i<=$#DATA2;$i++){
この部分の$#DATA2
は最終行までということでしょうか?

もし、行が2~15行だけ取得したいとき、
15に変えたとして、
$rankA++;
この部分で、おかしなことになりますよね・・?

投稿日時 - 2017-10-05 10:17:04