• ベストアンサー

foreachによるカウント方法

初心者です。 以下のことがうまくできません。ご教授ください。 ファイルの中身が ID1123 A/G AA NN AG GG NN AG GG GG GG GG AA AG ・・・ ID1000 C/T CC CT TT TT TT CT TT NN CT CC CT TT ・・・ ID9400 A/T AT NN AA AT TT TT AA AA AA AT TT TT ・・・ ・ ・ ・ ・ とあった場合の行ごとのカウント方法を教えて下さい。 考えたいるコードなんですが、 while (<>){ ($ID , $conbi , @moji) =split(/ / ); @count=(0,0,0,0,0,0,0); foreach(@moji){ ※この辺りが良くわかりません。    }   print OUT ~~~~~~ } のように考えています。 @countは、一行目なら(AAの数、AGの数、GGの数、NNの数、Aの数、Gの数、Nの数) を数えられるようにしたいと考えております。 どなたか教えて頂けないでしょうか?

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

  • ベストアンサー
  • kumoz
  • ベストアンサー率64% (120/185)
回答No.3

foreach (@moji) { $count{$_}++; } 上のコードを次のように変えると、1文字の個数も数えることができます。 (同じハッシュを使ってもよいのですが、出力が面倒なので別のハッシュに してあります。) foreach $item (@moji) { $count_1{$item}++; foreach $char (split //, $item) { $count_2{$char}++; } } NN と N だけが特別扱いで、その他は sort 順でよいのならば foreach で 除外しておいて後から出力することができます。 foreach $key (keys %count_1) { next if $key eq "NN"; $cnt = $count_1{$key}; print "$key:$cnt\t"; } print "$count_1{NN}\t" if exists $count_1{NN}; foreach $key (keys %count_2) { next if $key eq "N"; $cnt = $count_2{$key}; print "$key:$cnt\t"; } print "$count_2{N}" if exists $count_2{N};

nika_
質問者

お礼

ありがとうございます! カウント出来ました。 ですが、重要な点を忘れていました。 質問させて頂いた時に 「@count=(0,0,0,0,0,0,0);」 と書いた理由があります。 たとえカウント0でも記述出来るようにしたいと思っています。 もし、ある行で ID22 A/G AA AA AA AA AA AA AA とあった場合でも結果が AA AG GG NN A  G N   7  0  0  0  14 0 0 となるようにしたいんです。 今回のコードの場合、一度以上文字列が出来てこないと出来ないですよね? どうか参考となるご意見を頂けないでしょうか?

その他の回答 (3)

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.4

No3 です。肝心の sort を忘れていました。すみません。 次のように変更します。 foreach $key (sort keys %count_1) { ...

nika_
質問者

お礼

ありがとうございます! 全て解決できました。

回答No.2

> 行いたい結果は AA: AT: TT: NN:  のようにNNを最後にしたいと考えています。 そんなsort関数はないので、(1)sort関数を自作するか、(2)標準のsortをおこなってNN以外を順に出力して最後にNNを出力する、しかないでしょう。 > また、AやTやNの数は A=AAの結果を2倍+ATの数のように $a{'A'} = $a{'AA'}*2+$a{'AT'}; 文字が出現する回数を数える必要があるのなら、もっと汎用的な書き方をした方が後々も使えるでしょう。 文字の種類が増えるごとに計算式を書き直す必要がありますからね。

nika_
質問者

お礼

ありがとうございます。 >> 行いたい結果は AA: AT: TT: NN:  のようにNNを最後にしたいと考えています。 >そんなsort関数はないので、(1)sort関数を自作するか、(2)標準のsortをおこなってNN以外を順に出力して最後にNNを出力する、しかないでしょう (2)の方法で行うことにしました。 >> また、AやTやNの数は A=AAの結果を2倍+ATの数のように >$a{'A'} = $a{'AA'}*2+$a{'AT'}; ここなんです。No1の回答から、それぞれの行ごとなら $a{'A'} = $a{'AA'}*2+$a{'AT'}; という行ごとの書き方は分かったのですが、 連続した行を処理する際の汎用的な書き方が、思いつかないのです。 数千行以上あり、そこに出てくる文字はN以外で A、C、T、Gの4種類です。 何度も申し訳ありません。 ご教授お願い致します。

回答No.1

連想配列に入れたらいいでしょう。 foreach (@moji) { $a{$_}++; } print "AAの数: $a{'AA'}\n";

nika_
質問者

お礼

ありがとうございます。 ハッシュを用いて書いて見ましたが、 while (<IN>){ %count =(); ($ID,$conbi,@moji) = split(/\s+/,$_ ); foreach (@moji){ $count{$_}++; } foreach $key(keys(%count)){ $cnt = $count{$key}; print "${key}:${cnt}\t"; } print "\n"; } これで行ごとにカウントは出来たのですが、AAの数、AGの数、GGの数、NNの数の並びがうまく出来ません。 sort(keys(%count)) としても たとえば conbi が A/T だと AA:○○ AT:○○ NN:○○ TT:○○となってしまいます。 行いたい結果は AA: AT: TT: NN:  のようにNNを最後にしたいと考えています。 また、AやTやNの数は A=AAの結果を2倍+ATの数のように カウントした結果を用いて値を求めようとしたのですが、 上記のコードにどう記述したら良いかわかりません。 どうかご教授宜しくお願い致します。

関連するQ&A