• ベストアンサー

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の数) を数えられるようにしたいと考えております。 どなたか教えて頂けないでしょうか?

  • nika_
  • お礼率88% (24/27)
  • Perl
  • 回答数4
  • ありがとう数5

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

  • ベストアンサー
  • 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

  • 同じレコード単位で纏めて、違うレコードとの間に行挿入をしたい。

    同じレコード単位で纏めて、違うレコードとの間に行挿入をしたい。 A列~D列まで入力されて1000行あります。 A列を基準にソート済みなので以下のようになります。   A列  B列 C列 D列 A1 123   AA  BB  CC A2 123   DD  BB  CC A3 123   DD  EE  CC  A4 456   FF  GG  HH A5 456   JJ  KK  CC A6 789   JJ  LL  MM A7 789   NN  PP  QQ A8 789   RR  PP  CC これでA列の値が相違する場合そこに空白行を挿入したいです。   A列  B列 C列 D列 A1 123   AA  BB  CC A2 123   DD  BB  CC A3 123   DD  EE  CC  A4 A5 456   FF  GG  HH A6 456   JJ  KK  CC A7 A8 789   JJ  LL  MM A9 789   NN  PP  QQ A10 789   RR  PP  CC これを1000行手作業で行うのは大変なので一括で行いたいです。 方法はありますでしょうか? お願いします。

  • UPDATEについて(結合による)

    次のような操作がしたいのですが・・・ Test1 t1 t2 1 A 2 B Test2 tt1 tt2 tt3 1 1 AA 1 2 BB 2 1 CC 結果 Test1とTest2を関係付けて(Test.t1=Test2.tt1のinnerjoin) Test2.tt3が少なくともAAである場合に Test1.t2をDにしたいのです。 アドバイスあれば、宜しくお願いします。

  • テーブルごとのカウント

    PHP5.2+mysql 5.0.45で開発を行っております。 SQLに関する質問なのですが 以下のことが可能かどうかご教授いただきたく。 4つのテーブルがあります。 (例は適当です。項目の名称等は無視してください。) テーブルA ID Name Kana テーブルB ID NameID Pref City テーブルC ID NameID Tel Fax テーブルD ID NameID email CellPhone とします。 A.ID=1000の時各テーブルのレコード数が A:B:C:D=1:3:2:2となっています。 SQLの出力結果として A.ID A.Name A.Kana B.Count(ID) C.Count(ID) D.Count(ID) という、6項目を出力したいのですが 方法がわかりません。 試してみたのは select A.ID,A.Name,A.Kana,Count(B.ID),Count(C.ID),Count(D.ID) from A left join B on A.ID = B.NameID left join C on A.ID = C.NameID left join D on A.ID = D.NameID where A.ID = 1000 group by A.ID,A.Name,A.Kana ですが 結果、 A.ID = 1000 A.Name = Name A.Kana = Kana Count(B.ID) = 3 Count(C.ID) = 3 Count(D.ID) = 3 となってしまいます。 冷静に考えるとそうなんですが・・・ もしうまく結果を取得できる方法があればご教授いただきたく よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • Excel でデータのある行に番号をつけるには?

    Excel でデータが存在する行に番号をつける方法は? 表1から表3を得る方法を教授願います。フィルタと「編集」→「形式を選択して貼り付ける」が使えそうですが上手く行きません。 表1,2,3について説明します。 表1が原型。A列にはデータのないセルあり。表2でデータのあるセルをフィルタ表示し、上から1,2,3を入力。表3はフィルタを全表示にした結果。 表1 A B 1 aa 2 3 cc 4 5 ff 6 gg 7 8 ii 表2 1 aa 1 3 cc 2 5 ff 3 6 gg 4 8 ii 5 表3 1 aa 1 2 3 cc 2 4 5 ff 3 6 gg 4 7 8 ii 5

  • 重複を除くカウントの取得方法

    御晩です。 ----------------- <?php //カウント $id= "$k_id"; $id = mb_convert_encoding($k_id,"EUC-JP","SJIS"); $id_count = $DB->getone("SELECT count(*) FROM ".$k_koukoku_log_table." ".$k_koukoku_inp_table." where a_num =$k_id"); ?> カウント数は<?=$id_count?>です。 ----------------- 上記は重複もカウントされてしまいます。 ユーザー個々に広告番号があり($k_id)、その広告番号をクリックされた回数を同一人物(重複)を除いてのカウントを表示したいと思っています。

    • ベストアンサー
    • MySQL
  • group by したものをsumしたのですが方法がわかりません。

    ある情報をgroup byしその数をcountし、そのcountした数をsumしたのですがどのようにすればよろしいでしょうか? 例えば DB名 test a | ------ ABA | A | AA | ABA | select a,count(*) count from test group by a; a |count| ------------- ABA | 2 | A | 1 | AA | 1 | このカウントの数字を一回でsumすることは可能でしょうか? 宜しくお願いします。

  • 複数行のグループ集計とカウント

    下記の内容のようにグループ化してその後さらにグループ化してカウントを取る方法をお教えください。出来れば一回の処理で終わる方法が知りたいです。 大変お手数ですがよろしくお願いします。 例 t_id  t1  t2  1   a  1  2   a  1  3   a  2  4   a  3  5   b  4  6   b  4  7  ETC 5 ※1行目がフィールド名で2行目以降がデータです 1.上記の例のテーブルのt2のフィールドをグループ化し同じ数値をひとまとめにします >SELECT * FROM テーブル名 GROUP BY t2; t_id  t1  t2  1   a  1  3   a  2  4   a  3  5   b  4  7  ETC  5 2.この状態でt1のフィールドをグループ化してt1のカテゴリーのカウントをとり以下のような感じの結果を出したいと考えています。  t1 Count  a   3  b   1  ETC  1 このような処理を表示させるようにするにはどのようにしたらよろしいのでしょうかお教えください。 環境はmysql5.0を使用しております。

    • ベストアンサー
    • MySQL
  • 数列の計算方法

    A(t+1)=1/9At B(t+1) =At+4/9Bt+4/9Ct C(t+1) =4/9Bt+4/9Ct+Dt D(t+1) =1/9Ct B(0)=1 の計算をやりたいのですがどうすればいいのでしょうか?? 教えて下さい。よろしくお願いします。

  • Excelのマクロを作ってもらえますか?

    こんにちは。 エクセルのマクロで、Sheet1に転々と 入力されているデータを すべてA1の列へ統一して並べ替え(2) 同じデータの数を計算してB2へ記述する(3)などという マクロができるなら作っていただけないでしょうか? もし、数の入った行のみ残して削除までできれば最良なの ですが(4) (2) AA-20 AA-20 AA-20 BB-30 CC-30 CC-30 CC-30 (3) AA-20   3 AA-20 AA-20 BB-30   1 CC-30   3 CC-30 CC-30 (4) AA-20   3 BB-30   1 CC-30   3 このようになのですが、 お時間のあるときで結構ですので宜しくお願いします。

  • 文字列を分割して、分割した文字の一番右側を表示するにはどうしたら良いのでしょうか?

    Sub test2() Dim moji() As String Dim a As Range Dim 行 As Long For 行 = 2 To Cells(Rows.Count, 1).End(xlUp).Row Set a = Cells(行, 1) moji() = Split(a, "-") On Error GoTo moji Cells(行, 2) = moji(3) Next 行 moji: Cells(行, 2) = moji(2) End Sub で A列 B列 1-2-3-4 4 10-11-11-12 12 1-2-3-10 10 1-2-10-3 3 1-2-3 3 1-2 1-13 11-14 11-3 の結果になりますが1-2,11-14,11-3の部分が表示できません。 どなたかよいほうほうをお願いします。