• ベストアンサー

perl キーの集計について foreach文

@list=(20,25,24,32,28,20,28,24,20); という、ある組織の人間の年齢の配列を定義したとします。 そこで、 foreach $fld(@list){ $syukei{$fld}++; } というforeach文によって、年齢を「キー」として集計していくという説明を受けたのですが、いきなりスカラー変数の$syukeiが出てきて、さっぱりわかりません。 $syukei{$fld}++; という一行の意味を教えてくださらないでしょうか。 また、++という記号を使用していますが、これを別の書き方で書き換えることはできないでしょうか。

  • shevy
  • お礼率67% (703/1046)
  • CGI
  • 回答数5
  • ありがとう数6

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

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.5

> その場合なんですが、%syukeiの使用宣言というのは、 > 何をすればいいのでしょうか。 とりあえず、↓かな。   %syukei = (); これは「宣言」というほどのものではありません。 単なる「初期化」です。 しかも Perl が自動的にやってくれていることを、改めて書いています。 一見ムダのようですが、人が「プログラムを読む」ときに、これは宣言と同等の意味を持ちます。 たとえば、後にコードをメンテナンスしたり、他の人と共有することになったときに、これがないと1からコードを解読するハメになったりします(苦笑)。 さらに用途をコメントしておくなどすると、よりよいでしょう。   # 人数カウント用ハッシュ(キー:年齢、値:人数)   %syukei = (); また、より高度な話になってしまいますが、こんな宣言方法もあります。   my %syukei; これは「変数のローカライズ」というもので、変数を限定された場所だけで利用する場合の「宣言」です。(上記の単なる初期化とは異なります。) これを理解するには、まず「変数のスコープ」についての理解が必要なので、後の課題とされるとよいかと思います。 大きなスクリプトを書く時には必要にもなってきますが、今は特に気にしなくてもよいでしょう。

shevy
質問者

お礼

ありがとうございます。 初期化の方法、大変よくわかりました。 たしかに人のコードを読む際には、 他人がみてもよくわかるようなコードに仕上げる必要はありますよね。 まだまだ未熟ですが、perlの面白さにはまりつつあります。 がんばります。 ご丁寧にありがとうございました。

その他の回答 (4)

  • leaz024
  • ベストアンサー率75% (398/526)
回答No.4

「ハッシュ(連想配列)」というのはご存知ですか? これは配列と同様に、1つの変数内にいくつもの値を格納できるタイプの変数です。 配列は @var で表し、$var[ 添字 ] という形式で各要素にアクセスしますよね。 添字は0から始まる正の整数値で、このため要素の並びが保持され、データを順次処理するのに向きます。 ハッシュは %var と表し、$var{ 添字 } という形式で各要素にアクセスします。 添字は「キー」と呼ばれる「文字列」であるため、配列とは異なり要素の並びが保持されません。 問題の   $syukei{$fld}++; は、暗黙のうちに %syukei というハッシュ変数を用意し、キーが $fld である要素の値をインクリメントしています。 (本当はループ前に %syukei の使用宣言をした方がよいです。) 各要素の初期値は「未定義値(数値としては 0)」なので、上記スクリプトでは「年齢ごとの人数」をカウントしていることになります。 ハッシュの各要素を取り出すには、keys 関数を使うのが一般的です。 keys はハッシュの全てのキーをリストにして返します。   foreach $key (keys %var) {     print "$key => $var{$key}\n";   } keys が返すキーの並びは内部的なものなので、これを年齢(数値)順にしたいときは sort 関数を使って次のようにします。   foreach $key (sort {$a <=> $b} keys %var) {     print "$key => $var{$key}\n";   } ※詳しくは sort 関数について調べてみてください。

shevy
質問者

お礼

回答ありがとうございます。 やっと意味がわかりました。 最初は各要素の初期値は未定義値なんですね。 それでゼロがあり、 また、最初に %syukeiとして、宣言しておいたほうがよいということですね。 その場合なんですが、%syukeiの使用宣言というのは、 何をすればいいのでしょうか。 ハッシュについては、まだ勉強を始めたばかりで、 配列のほうがイメージしやすかっただけに、 キーという概念を捉えるのが非常に困難を極めておりました。 ですが、すこし光がさしてきたように思えます。

  • ikspiari
  • ベストアンサー率48% (29/60)
回答No.3

連想配列というのは、キーがユニークな値なんですね。 ですから、 @list=(20,25,24,32,28,20,28,24,20); を foreach $fld(@list){ $syukei{$fld}++; } で、連想配列に格納していくと以下のような結果になります。 $syukei{'20'} = 3; $syukei{'24'} = 2; $syukei{'25'} = 1; $syukei{'28'} = 2; $syukei{'32'} = 1; ソースの最後に以下を追加してみてください。 while ( ($key,$val) = each(%syukei) ) { print "$key=$val\n"; } 連想配列の仕組みが分かると思いますよ。 ちなみに連想配列の値は何も数値でなくても構いません。 上記ソースの%syukeiを%ENVにすると環境変数が出力されます。 参考になれば幸いです。

shevy
質問者

お礼

ありがとうございました。 ソースの最後に教えてくださった一文を加えて、 ブラウザで確認をしてみました。 連想配列とは非常に難しいというか、慣れるまでは、使いにくいですね。 でも、おかげさまで、今はしんどいですが、 もうしばらくがんばればなんとかなりそうな気もしてきました。 ご丁寧にありがとうございました。

  • ikspiari
  • ベストアンサー率48% (29/60)
回答No.2

$syukei{$fld}++; は連想配列と呼ばれるものです。 $syukeiという変数のキーに$fldが入ります。 ここでは値に++として数値を1ずつプラスしています。 @listの内容から集計結果は例えば、 $syukei{'20'} = 3; となります。 @listの配列に20が3つありますよね。 ちなみに連想配列は%で現します。 この例では、%syukeiに連想配列が格納されます。

shevy
質問者

お礼

ありがとうございます。 回答を何度も読ませていただきましたが、 まだ理解に苦しんでいます。 >$syukeiという変数のキーに$fldが入ります。 とのことですが、となると、まず、一番先頭の 20が入るということですよね。 それに、++していくのですから、 20が21になるような気がするのですが、 これは違うとは思うのですが、説明ができない状態です。 foreach文は繰り返し処理をする命令文なので、 なぜ、++を毎度してあげるのかということもわからなくなってしまいました。 一番最初の年齢の「20」というのは、初期値がゼロで、初めて出てきた段階で、++により、ゼロから1にカウントされるのでしょうか? ちぐはぐな文章になってしまいましたが、もう一度アドバイスいただけないでしょうか。 宜しくお願いします。

  • nightowl
  • ベストアンサー率44% (490/1101)
回答No.1

$syukei(集計)という変数は、おそらく年齢が現れる頻度を格納するものでしょう。 foreach ループで配列 @list の要素を順に見ていって、 20歳だったら $shukey{20} の値が一つ増えると。 >++という記号を使用していますが、これを別の書き方で >書き換えることはできないでしょうか。 $syukei{$fld} = $syukei{$fld} + 1; と同じ意味ですが、長くなるので誰もこのような書き方はしませんね。

shevy
質問者

お礼

ありがとうございます。 nightowlさんのおっしゃられるとおりで、 年齢が現れる頻度が格納されるようです。 ですので、20歳は3つとなります。 実は、何度も回答を読み直したのですが、 まだ理解できないんです。 まず、いきなり$syukeiというスカラー変数が出てくるのであれば、 $syukei= という形で入るべきではないかと思うのですが、 どうもわかりません。 また$syukei{$fld}で、$syukei{20}の場合、 $syukei{$fld}++だと、20,21,22と増えていくのではないのでしょうか?それは違うとわかっているつもりなんですが、説明しろと言われると、自分ではどういえばいいのかわからない状態です。 頭の中がぐちゃぐちゃになってしまいました。 $syukei{$fld}=$syukei{$fld}+1; と書き換えられるという意味は理解致しました。 foreachの文章の中に、 ++という演算子を用いるということがイメージしにくくて困っています。 もう一度アドバイスお願いできますでしょうか。 宜しくお願いします。

関連するQ&A

  • ハッシュの値のグループ化について

    入門本に、次のような例題がありました(主要部分の抜粋です)。 @list = (20,25,24,32,28,20,28,24,20); #年齢リスト foreach $fld(@list){   $syukei{$fld}++; } print "<table><tr><th>年齢</th><th>人数</th></tr>\n"; foreach $key( reverse( sort( keys( %syukei ) ) ) ){   $cnt = $syukei{$key};   print"<tr><th>${key}才</th><th>${cnt}人</th></tr></table>\n"; これの実行結果は、@list の年齢を各年齢ごとにカウントして、表に各年齢が何人であるかを表示します。 ・$syukei{$fld}++; の部分は $ハッシュ名{'キー名'} でハッシュを作ろうとしているのだと思うのですが、++ がなぜ付くのか分かりません。 ・↑の考え方が合っているとしたら、$cnt = $syukei{$key} で右辺は $ハッシュ名{'キー名'} を表しているのだと思うのですが、左辺がスカラー値を求めている場合はキーの数を返すというルールがあるのでしょうか? 私の質問にこだわらず、分かりやすく全体の説明をして頂ければ助かります。

    • ベストアンサー
    • Perl
  • foreachについて

    ポケットリファレンスより foreach[★](□){■} 配列などの一連のスカラー値を持つリスト□から順に要素を取り出し、スカラー変数★に代入してからブロック内の■を繰り返し実行します。リスト値□がなくなった段階で終了します。 とあります。今解析しているプログラムで下記のようなコードがあり、数点質問があります。(このコードの前にあるDBを呼んで、$RECにデータを返しています) undef @BCOL; my($KU_REC); while ($rc = $DBr->fetchrow_hashref) { $flg_find_ku = 1; foreach $KU_RECt (@BCOL) { if ($KU_RECt->{KU_CODE} eq $REC{KU_CODE}) { $KU_REC = $KU_RECt; $flg_find_ku = 0; last; } $KU_REC = $KU_RECt; } if ($flg_find_ku == 1) { (1) push(@BCOL, {}); (2) $KU_REC = $BCOL[$#BCOL]; } } (1)@BCOLは最初要素を含んでいないように思うのですが、リファレンスの(リストの値がなくなるまで)という部分をみて疑問ですが、リストに値がないのに、foreachの中をとおるのでしょうか? (2)たとえば、とおったとして、このロジックはおなじ区コードを見つけて、見つかればフラグを0にするという処理だと思うのですが、最初の一回目は(1)(2)をとおると思います。この処理が何をしているかわかりません。@BCOLに{}を入れるとどうなるのでしょうか? また、$#BCOLは配列の引数をあらわしているように見えるのですが、いったい何番目の意味なのでしょうか? (3)スカラー変数は基本的にmyなどで宣言するかと思うのですが、foreachで使われる変数$KU_RECtの定義がみつかりません。ということはこの場合変数定義はいらないものと思ってよいのでしょうか? 私が何か勘違いしている部分もあるかと思うのですが、わかる方、どうぞよろしくお願いいたします。

    • ベストアンサー
    • Perl
  • foreach文

    foreach文の使い方について質問です。変数rowには任意のデータが格納されているものとします。①と②はどのように使い分ければいいですか? ①foreach ($row as $キー名 => $キー名にリンクする配列に格納された値が格納される変数){ ループで実行される処理 } ② foreach ($row as $配列が順に格納される変数名){ ループで実行される処理 }

    • 締切済み
    • PHP
  • foreachとかの勝手な省略?

    PHP初心者です。 foreachを使うときに、参考サイトのソースを見て???だったのですが、 例えば以下の場合に foreach($_POST['hoge'] as $key => $val){ echo "$key : $val \n"; } とありますが、hogeは自分で決めたものなので分かるのですが、 見に覚えの無い$key => $valといった変数で動作しています。 $keyや$valは自分で定義した覚えはありません。 調べると$keyは分かりませんが、$valはvalueの省略みたいな記述がありました。 また、他には更に短縮され、$kとか$vしか記述されていないソースもあり、 試すとこれでも正常に動いています。 これはどういうことなのでしょうか? 何か決まりがあるのでしょうか。 ちなみに、チェックボックスの配列取得の定義に使いました。 私からはただ勝手に短縮しているようにしか見えず納得いきません。 お詳しい方、どなたかアドバイス頂けないでしょうか。 宜しくお願いします。

    • ベストアンサー
    • PHP
  • foreachについて

    下記の配列についてitem2の値のみ取り出したいのですが、 foreach($food as $key1=>$array){ foreach($array as $key2=>$array2){ echo $food["$key1"]["item2"]; } } foreachで回して取り出すと555444333となります。 543という結果が欲しいのですが、 実際には下記の配列が数百と大量にあり、一次元配列の数字は下記のように0から1ずつ増えていきます。(二次元目のキーは全てitem0~item2となっています) キーの変更をしないでitem2の値のみ一度に取り出すにはどうしたらよいのでしょうか? (取り出す前に配列の削除などのプログラムもあるため、0から順番に並んでいるとは限りません。 ) $food["0"]["item0"]="y"; $food["0"]["item1"]="bi"; $food["0"]["item2"]="5"; $food["1"]["item0"]="y"; $food["1"]["item1"]="dou"; $food["1"]["item2"]="4"; $food["2"]["item0"]="n"; $food["2"]["item1"]="co"; $food["2"]["item2"]="3";

    • ベストアンサー
    • PHP
  • foreachについて

    phpを今勉強中なのですがforeachで少し分からない部分があります。 例えば(1)はnのある配列を消去するだけのプログラムでして、これを (2)のように書き換えてみると、全て表示されてしまい、(1)と同じ動きをしません。 phpマニュアルを読む限り同じ動きをすると思うのですが、array_keys($key1)の中に うまく一時配列のキーが入っていないように思います。 どうしてでしょうか? (1) <?php $food["y"]["bb"]= "k1"; $food["n"]["bb"]= "k2"; $food["n"]["cc"]= "k3"; $food["k"]["dd"]= "k4"; foreach($food as $key=>$key1){ foreach($key1 as $key2=>$key3){ if($key=="n") unset($food[$key][$key2]); } } echo "<pre>"; print_r($food); echo "</pre>"; ?> (2) <?php $food["y"]["bb"]= "k1"; $food["n"]["bb"]= "k2"; $food["n"]["cc"]= "k3"; $food["k"]["dd"]= "k4"; foreach($food as $key=>$key1){ foreach($key1 as $key2=>$key3){ if(in_array("n",array_keys($key1))) unset($food[$key][$key2]); } } echo "<pre>"; print_r($food); echo "</pre>"; ?>

    • ベストアンサー
    • PHP
  • 連想配列のキーを得るには

    $xx = array('a' => 'd'); こういう連想配列がどこかで定義されていて、キー名が不明の$xxから唯一のキーである'a'を得るにはどうしたらいいですか? foreach()でできますが、素直に得る方法があると思います。

    • ベストアンサー
    • PHP
  • foreachで=>はどういう意味ですか?

    foreach ($val as $v=>$key)の=>はどのような意味なのでしょうか? google検索では=>が記号のため検索できません。 使い方と機能を教えて下さい。 どうぞよろしくお願い致します。

    • 締切済み
    • PHP
  • foreachで一致した説明文を表示(初心

    この間ポケモン図鑑について質問させていただいた者です。(ID違いますけど^^; http://oshiete1.goo.ne.jp/kotaeru.php3?q=1649007 変な質問をしてるかもしれませんm(_ _)m @list内には 手持ち・・(略)<>あくしゅう<> ほのお・こお・・<>あついしぼう<> 戦頭に出ると・・<>あめふらし<> このように1つ目に説明文、2つ目に(特性の)名前が入っています。 それを、 foreach(@list){ ($content,$name)=split(/<>/); } こんな感じでスカラー変数に代入してるのですが、 各ポケモンのデータを表示するページで説明文を表示するにはどうすればいいのでしょうか? 「$end_tokuse」というスカラー変数にあらかじめ各ポケモンの特性の名前は入っていて、それを上の処理と一致するか、しないかでこんな感じで print <<EOM; <table><tr><td> EOM ここに上の処理を print <<EOM; </td></tr></table> EOM 持って来て表示させようかと思っていたのですが、表示するデータの量がほかにもたくさんありすぎていちいち切っていると 編集が大変面倒になるので、一致した説明文をスカラー変数に代入して print <<EOM; <table><tr><td> $setume </td></tr></table> EOM このようにしたいのですが、どうすればいいかわかりません。 一致した説明文をスカラー変数に代入して表示させるにはどうすればいいですか。 わかりにくいですがよろしくお願いします。

    • ベストアンサー
    • Perl
  • foreach文について、今朝、回答いただいて、その時は分かったつもり

    foreach文について、今朝、回答いただいて、その時は分かったつもりだったのですが、 やっぱりよく分かっていなかったようなので、もう一度質問させてください。 今朝質問した内容は、下記です。 ▼配列の要素の値をループ中に変更して確認したいのですが、   http://okwave.jp/qa/q5943567.html 例えば、下記例のとき、上記と挙動が異なるのは、なぜでしょう? このforeachでは、値を書き換えできないので、 そもそも、上記と比較をしてはいけないのでしょうか? $arr = array("値1", "キー1" => "値2", "値3"); foreach($arr as $val){ $val = "{$val}の値利用"; echo $val."<br />"; } foreach($arr as $val){ echo $val."<br />"; } 1)$arrの内容を$valにコピー 2)$valに値を代入 3)$valを表示 4)1)へ戻る で、特に分からないのが、以下です。 上のforeachで、 代入後の値が表示されるのは、 なぜでしょうか。 今朝質問した「$arr as $key => $val」 のときと比較して、 どなたか解説していただけないでしょうか?

    • ベストアンサー
    • PHP

専門家に質問してみよう