入門本に、次のような例題がありました(主要部分の抜粋です)。
@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} で右辺は $ハッシュ名{'キー名'} を表しているのだと思うのですが、左辺がスカラー値を求めている場合はキーの数を返すというルールがあるのでしょうか?
私の質問にこだわらず、分かりやすく全体の説明をして頂ければ助かります。
No.3ベストアンサー
- 回答日時:
手ごわいですね。
敢えて説明に挑戦してみます。どうも、ハッシュの概念またはハッシュの記法の
理解が間違っておられるように見受けられますが。
ハッシュって要はExcel(じゃなくてもいいですが)の
表みたいなもんで、表の左端の列に書かれてる内容で
行を特定する、というイメージです。
回答者 回答日
deagle 01-09-07
zeyper 01-09-07
Fooky 01-09-09
という表があったとします。表の名前はAnsDateとでも
しましょうか。ハッシュでは、回答日を取り出すのに、
回答者の名前を使って取り出せる、ということです。
ですから、print $AnsDate{'Fooky'}; の実行結果は
01-09-09となります。このときの回答者名が
「ハッシュキー」、回答日が「ハッシュ値」となります。
表全体が「ハッシュテーブル」、各行が「ハッシュ」と
呼ばれます。
1つ、Excelの表と違うところは、同じ回答者名を持った
行(=同じハッシュキーを持つ異なるハッシュ値)はつくれない、
ということです。ですから、ここで新たに全く同じハンドル
ネームのFookyって人が、10日に回答をしてしまうと、
$AnsDate{'Fooky'} = '01-09-10';という代入が為され、
先程の表は
回答者 回答日
deagle 01-09-07
zeyper 01-09-07
Fooky 01-09-10
となってしまいます。
一方、普通の配列は、何行目かを指定することで
データを取り出す表、というイメージになります。
ですから、先程の表は、
番号 回答日
0 01-09-07
1 01-09-07
2 01-09-09
となり、0番目の回答者が何日だったかなぁってことで、
print $AnsDate[0];として、01-09-07を取り出します。
ちょっと難しく考えすぎではないですか?
要素番号でしか参照できない配列が、
もうちょっと使いやすくなって、要素番号の
ところに任意の文字列が使えるようになった
だけのことなんですが。
さて、例題のforeachのところを展開してみると、
$syukei{'20'}++;
$syukei{'25'}++;
$syukei{'24'}++;
....
$syukei{'28'}++;
$syukei{'24'}++;
$syukei{'20'}++;
という処理が順に行われているだけです。
ここで新たに問題になるのは、$syukei{'20'}という
のは初めて出て来たので、文字列'20'をキーとする
ハッシュはまだ存在しない(=まだ表の左端に20
と書かれた行が存在しない)ということです。
まだ存在しないハッシュ値に対して、1増やす、
という算術演算を施したらどうなるのか?
答えは、'20'をキーとして、ハッシュ値が'0'である
ハッシュが自動的に作成され、それに1増やす
という処理が行われます。
そうすると、最終的に、
$syukei{'20'} == 3, $syukei{'25'} == 1, $syukei{'24'} == 2,
$syukei{'32'} == 1, $syukei{'28'} == 2
という結果になるのは、不思議ではないと思うんですが。
しつこいようですが、この結果を表として書くと、
年齢 人数
20 3
25 1
24 2
32 1
28 2
という表になります。
例題の後半は、年齢の大きいものから順に表示される
ように工夫しているだけです。
ありがとうございます!ゆっくり考えて、大方理解できました。
私が分かってなかったのは、$syukei{$fld}++; の加算がどの時点行われるか、ということです。私は $fld の値(年齢の数値)に加算されるものだと勘違いしていました。
Fookyさんのおっしゃる「存在しない値に1を加算する」という概念がなかったんです。
foreach $fld(@list){
$syukei{$fld}++;
の時点で、目には見えないけどハッシュテーブルを作ってるんだと理解すれば、$syukei{$fld}++; の指し示す行へ1が加算されるのも分かります。
その後の
foreach $key( reverse( sort( keys( %syukei ) ) ) ){
$cnt = $syukei{$key};
も、それで理解できました。
No.2
- 回答日時:
初めまして、私も最近勉強を始めたものです。
まず、ハッシュとは
aaa-bbb0-ccc0
-bbb1-ccc1
-bbb2-ccc2
と言う感じになっていてこれは、%aaaというハッシュになります。
%aaaのbbb0の中に、ccc0と言う値が入っているわけです。
ちなみにこれが@aaaだと、bbb0は数字0、bbb1は数字1でccc0がその値となります。
ですから、ハッシュとは、値(ccc)を入れるだけでなく、その値の入っているキー(bbb)も決められる、配列(@)のパワーアップ版みたいなものだと思ってください。
余計に分からなくなったらすいません。
ハッシュが分かったところで(分からなくても(笑))上のプログラムは、
syukei-20-3
-24-2
-25-1
-28-2
-32-1
と言うハッシュになります。++は下の専門家の言った通りだと(下を読んで初めて知った)数字を1足す、"$***++"と同じ効果があると言うことなので、
syukei-20-
と初めて20を出したら++で
syukei-20-1
とし、もう一度20を出したら++で、
syukei-20-2
として、それを最後に
$cnt = $syukei{$key};
で$cntに値を入れているというわけです。ちなみにこの時$keyが20だと
3 = $syukei{20};
となります。
こんな雑な説明でわかっていただけたら幸いです。
最後にこの時
$abc = @list;
とやると$abcには9が入ります。
配列をスカラー変数に入れると、配列の中のリストの数を返します。
$ハッシュ名{'キー名'} はキー名の中のスカラー変数を表しているので、$***の中にはスカラー変数を返しているだけです。
ありがとうございます。しかし、
foreach $fld(@list){
$syukei{$fld}++;
}
の部分は $fld に @list の要素を一通り代入しなさい、という命令ですよね?
それがなぜ @list の各要素をキーとして代入し、その登場回数を値として代入するのかが分かりません。
配列をスカラー変数に入れると、配列の中のリストの数を返すというのは分かりましたが、 「$ハッシュ名{'キー名'} はキー名の中のスカラー変数を表しているので、$***の中にはスカラー変数を返しているだけです。 」という説明が分かりません。
No.1
- 回答日時:
またまた登場(笑)
えー。まずこのプログラムは、ハッシュ配列 syoukei に、年齢をキーとしてその人数を入れ、逆順ソートした上で出力する、というものですね。
ちょっとばかしHTMLの組み方がおかしいようですが(笑)
で、ご質問の部分、の「++」は、これは単純に「カウントアップ」の意味です。
$syoukei{$fld} には「$fld 歳」の人の人数が入っているわけですから、これにプラス1しているのです。これを、インクリメント機能と呼びます。
このカウントアップ自体はハッシュに関する機能ではなく、すべての変数に対して使うことが出来ます。
(すべての変数は未定義状態では0、null、undefine のいずれかであると定義されるので、最初のカウントアップの直後には変数の値は1になります)
逆に $syoukei{$fld}--; とするとこれはカウントダウンで、マイナス1されます。
ですので、$cnt = $syoukei{$fld} では、$cnt に単純に、カウントアップして得られた集計結果を代入しているだけということになります。
@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";
私の解釈では、
■foreach $fld(@list){ は、@listの要素を一通り$fldにする→従って $syukei{$fld} は $syukei{$20} など@listにある年齢を入れたもの9つを用意する→$syukei{$20}++ なんていう文は成り立たないのでは?
となって、止まってしまいます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP htmlで複数の個数入力欄を表示させるには 1 2022/09/20 03:11
- Visual Basic(VBA) Selenium.ChromeDriverの使い方について 7 2022/09/22 06:43
- その他(プログラミング・Web制作) pythonにおける単方向リストの実装について 4 2022/07/13 12:34
- AJAX JavascriptからPHPへのAjax通信でnullが返ってくる 3 2022/08/03 22:00
- 作詞・作曲 中森明菜『ミ・アモーレ』の歌詞では、ISAS打ち上げの小惑星探査機ハヤブサの数奇な運命を暗示してる? 2 2022/11/18 19:51
- 洋画 映画『ヘルレイザー』(2022年)の最新作は勿論露国プーチン大統領。ウクライナ戦争を題材に構成? 1 2022/11/19 16:37
- 数学 2*2の行列に対して固有値の最大実部を与えるkの値を求めたい 3 2022/11/08 16:26
- HTML・CSS 自身のHPにYouTube動画を貼り付けるのが出来なくなり困ってます 1 2022/11/11 10:44
- PHP PHPでCSVを出力するさいに、ループの中で前の行の値を変更したい 1 2022/10/27 14:21
- HTML・CSS テーブルタグのセルの幅の一部だけを指定 1 2023/03/12 12:02
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ハッシュ検索はなぜ速い
-
文字列を変数名として扱う方法
-
ハッシュのハッシュを実現したい。
-
CPANの「Mail::Mailer」 Retur...
-
画面を強制的に再描画させる方法
-
VBAでの一時停止と再開の方法
-
Escキーを押すと、中断する時と...
-
VBAで3秒だけ時間を止めたい
-
Javaでゲーム
-
UWSCの終了の仕方
-
VBのReturnの使い方
-
Do whileでExitせず、ループの...
-
二次元配列のインデックスについて
-
アクティブセルから、A列最終行...
-
VBAのautofilter、criteriaの配...
-
DoEventsが必要な理由について
-
DOSコマンドのループ内のTIMEコ...
-
ボタンが押された時にループか...
-
C言語 4) int 型配列 month を...
-
配列を初期化する時ってどうす...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
データベースでユーザーのパス...
-
文字列を変数名として扱う方法
-
ハッシュ検索はなぜ速い
-
まったく同じファイルのハッシ...
-
列挙型と連想配列の違いを教え...
-
ハッシュ値が一致したデータは...
-
重複ファイルを削除したいので...
-
*(アスタリスク)の意味
-
UTF-8で書かれたJSPの日本語文...
-
チェックデジットについて
-
ハッシュマーク以降のアドレス取得
-
ハッシュリストって単にハッシ...
-
一意(ユニーク)かつ、ソート...
-
多次元連想配列の削除
-
英語でのシャープとコメの呼び...
-
perlで配列名を動的に作り出したい
-
連想配列のサイズ制限
-
ハッシュ値によるファイルの同...
-
全ての変数を初期化する方法は...
-
文字列をハッシュにしなければ...
おすすめ情報