(7)11/09の授業内容
- ハッシュ
- ハッシュへの値の追加
- ハッシュから値を取り出す
これまでは配列を繰り返し使用してきました。ハッシュについて話をする前に、まず配列の確認をしておきましょう。配列は、インデックスを用いて値を順次代入したり、取り出したりするために使用してきました。以下ではデータが数字の場合と文字列の場合を両方とも示します。
laputa = [] laputa[0]="パズー" laputa[1]="シータ" laputa[2]="ドーラ" laputa[3]="ムスカ" laputa[4]="ルイ" laputa[5]="アンリ" p laputa[2] #=>"ドーラ"
gakushoku = [] gakushoku[0]=350 gakushoku[1]=350 gakushoku[2]=250 gakushoku[3]=250 gakushoku[4]=120 gakushoku[5]=450 p gakushoku[2] #=>250
ハッシュも、配列と同様に複数のデータを格納することができます。配列ではインデックスを使用しましたが、ハッシュではキーを使用し、数字以外を利用することができます。このキーを使ってデータを代入したり、取り出したりします。
laputa = Hash.new laputa["pazu"]="パズー" laputa["sheeta"]="シータ" laputa["dola"]="ドーラ" laputa["muska"]="ムスカ" laputa["louie"]="ルイ" laputa["henri"]="アンリ" p laputa["dola"] #=>"ドーラ"
gakushoku = Hash.new gakushoku["カレー"]=350 gakushoku["ラーメン"]=350 gakushoku["そば"]=250 gakushoku["スパゲティ"]=250 gakushoku["ソフトクリーム"]=120 gakushoku["夕定食"]=450 p gakushoku["そば"] #=>250
laputa = Hash.new:laputaがハッシュであることを宣言(からっぽのハッシュを作っている)。
laputa['pazu']="パズー":laputaの持つハッシュの"pazu"に対応する値として"パズー"を代入しています。配列のインデックスに相当するものをハッシュではkeyと呼び、keyに対して結び付けられたデータをvalueと呼びます。
プログラムを書く段階で初期値を入れる場合、配列は gakushoku=[350,350,250,250,120,450]とかかれたのに対して、ハッシュではkey => valueというように、keyとvalueのペアを並べて書かれます。ペアとペアの区切りにはカンマをつけ、配列とは異なり{}で囲んで示します。
gakushoku = {"カレー" => 350, "ラーメン" => 350, "そば" => 250, "スパゲティ" => 250, "ソフトクリーム" => 120, "夕定食" => 450}
laputa = {"pazu" => "パズー", "sheeta" => "シータ", "dola" => "ドーラ","muska" => "ムスカ", "louie" => "ルイ", "henri" => "アンリ"}
記述をする際には、下記のように適宜改行を入れて見やすく書くこともできます。
gakushoku = { "カレー" => 350, "ラーメン" => 350, "そば" => 250, "スパゲティ" => 250, "ソフトクリーム" => 120, "夕定食" => 450 }
このようにしてgakushokuに入ったハッシュの値は、配列と同じように[]で取り出すことができます。
p price["カレー"] → 350 p price["ソフトクリーム"] → 120
ハッシュの初期値を囲む括弧は中括弧 {} ですが、ハッシュの値を取り出す時や代入する時に使うのは大括弧 [] であることに注意が必要です。
実際にプログラムを動かしてみましょう(keroro.rb)。
#!/usr/koeki/bin/ruby keroro = Hash.new("いない") keroro["ケロロ"] = "軍曹" keroro["タママ"] = "二等兵" keroro["ギロロ"] = "伍長" keroro["クルル"] = "曹長" keroro["ドロロ"] = "兵長" STDERR.print "ケロロ、タママ、ギロロ、クルル、ドロロ、のだれの階級を知りたいですか?\n" what = gets.chomp! kaikyu = keroro[what] printf("%sは%sであります\n", what, kaikyu) if kaikyu == "いない" print "ちゃんと入力してほしいであります。\n" end
以下に実行例を示します。ktermでの日本語入力のON/OFFはShift+SPACEです(シフトを押しながらスペースキーを押す)。
% ruby keroro.rb ケロロ、タママ、ギロロ、クルル、ドロロ、のだれの階級を知りたいですか? タママ タママは二等兵であります
keroro = Hash.new("いない"):Hash.new(値)で、定義されていないkeyが代入された場合に、この値が返されるようになります。上記のプログラムで("いない")をとりのぞいてkeroro = Hash.newとした場合に、未定義のkeyを入力するとどのようになるか調べてみよう。
配列にデータが格納できるのと同様に、ハッシュにもデータを格納することができます。ただし、この際にはkeyとvalueのいずれも与える必要があります。以下のプログラムはプロ野球チームの親会社とチーム名を順番に読み込んでハッシュに格納するものです(baseball.rb)。
#!/usr/koeki/bin/ruby ball = Hash.new # 新しいハッシュの生成 while true STDERR.print "親会社(登録終了の場合は おしまい と入力): " company = gets.chomp! if company == "おしまい" break end STDERR.print "チーム名: " team = gets.chomp! ball[company] = team end STDERR.print "読込終了\n" $KCODE = 'e' # 漢字コードをEUCにしてから p ball # pメソッドでハッシュの値を全表示
実際に動かしてみましょう。
% ruby baseball.rb 親会社(登録終了の場合は おしまい と入力):西武 チーム名:ライオンズ 親会社(登録終了の場合は おしまい と入力):オリックス チーム名:バファローズ 親会社(登録終了の場合は おしまい と入力):読売 チーム名:ジャイアンツ 親会社(登録終了の場合は おしまい と入力):ソフトバンク チーム名:ホークス 親会社(登録終了の場合は おしまい と入力):阪神 チーム名:タイガース 親会社(登録終了の場合は おしまい と入力):おしまい {"西武"=>"ライオンズ", "オリックス"=>"バファローズ", "読売"=>"ジャイアンツ", "ソフトバンク"=>"ホークス", "阪神"=>"タイガース"}
ハッシュから値を取り出す方法について、配列と比較をしながら見てみましょう。いずれもレジにてレシートを作成するプログラムを想定しています。購入したものと金額はバーコードにより読み取り済みであり、配列、ハッシュに入力されているものとします。
配列を使用した場合は下記の通りとなります(receipt-hairetsu.rb)。商品が代入された配列itemと、金額が代入された配列kingakuという2つの配列を使用しています。配列からの値の取出しにはインデックスを使用するため、初期値を0とするiという変数を使用し、while文で繰り返し表示をしています。
#!/usr/koeki/bin/ruby item = ["牛乳","醤油","玉葱","納豆","林檎","牛肉",] kingaku = [98,298,198,128,300,698] i = 0 sum = 0 while i < kingaku.length sum += kingaku[i] printf ("%s\t%d円\n",item[i],kingaku[i]) i += 1 end printf ("合計\t%d円\n",sum)
ハッシュを使用した場合は下記の通りとなります(receipt-hash.rb)。ハッシュの場合、インデックスではなくkeyとvalueを用いているため、iの値を1ずつ増やしながら繰り返し表示をするwhile文を使用できません。ここではfor文を使用しています。shina、moneyにはそれぞれkey、valueの値が代入されます。
#!/usr/koeki/bin/ruby kingaku = { "牛乳" => 98, "醤油" => 298, "玉葱" => 198, "納豆" => 128, "林檎" => 300, "牛肉" => 698 } i = 0 sum = 0 for shina, money in kingaku printf ("%-10s\t%5d円\n",shina, money) sum += money end printf ("合計\t%d円\n",sum)
receipt-hash.rbを実行した結果は下記の通りです。ハッシュの場合、代入した順番と結果の順番が異なります。
% ruby receipt-hash.rb 牛乳 98円 牛肉 698円 林檎 300円 納豆 128円 玉葱 198円 醤油 298円 合計 1720円
課題
以下の1番についてプログラムを作成してください。余力のある方は1番ではなく2番のプログラムを作成してください。1番が難しい方は3番を作成してください。
- 授業中に使用したreceipt-hash.rbでは、既に購入品名と金額がハッシュに代入されていた。これを改良し、品物と金額を順番に入力することでレシートを表示するプログラムを作成してください(9点満点)
- 1番と同じだが、品物と金額を順番に入力するのではなく、これらを記述したテキストファイルから読み込んでレシートを表示するプログラムを作成してください。このプログラムを作成するためにはopenメソッドと正規表現を使用する必要があります(10点満点)
- 授業中に使用したkeroro.rbを見本に、自分の好きなデータをハッシュに代入しておき、あとから検索できるプログラムを作成してください。検索できるデータは誕生石、12星座と誕生日、アニメのキャラクタと声優、山と標高、国と首都など好きなものを選んでください。他の人とは違うもの、楽しいものが望ましい。最低でも10個以上のデータを作ること(ハッシュを10個ではなく、データが10個以上代入されているハッシュ変数を1つ作るということ)(8点満点)
作成したプログラムや実行結果をメールでnaoya@e.koeki-u.ac.jp宛に送る
課題の提出期限は11月15日(火)23:59までです
メール送信時の注意
- Subjectは「学籍番号-1109」とすること
- メール本文は下記の構成で記載すること
- プログラム(メールに貼り付ける)
- プログラムの実行結果
- プログラムの説明
- 感想
- 自由製作課題に関する意見(前回の質問に対する皆さんの意見を読んだ上で、再度グループと個人とどちらがよいか回答してください。これを最終アンケートとします)
説明のポイント(1番と2番):ハッシュとは何か、ハッシュへの値の代入、ハッシュからの値の取り出しの3点について説明がなされていること(2番を選んだ人は正規表現とopenメソッドについても説明すること)。単にWEBページをコピーペーストしたものは減点対象とする
説明のポイント(3番):使用したデータについて、ハッシュとは何か、プログラムの各行の説明を行うこと。単にWEBページをコピーペーストしたものは減点対象とする
レポート採点基準(1番と2番):期限内提出(2点)、プログラムの正誤(2〜3点)、レシートの見栄え(1点)、説明(3点)、指示通りにメールを送っているか(1点)
レポート採点基準(3番):期限内提出(2点)、プログラムの正誤(2点)、説明(3点)、指示通りにメールを送っているか(1点)
Tips
emacsについて
- emacsで新しいファイルを作成する場合は,C-x C-fを押し,ミニバッファにkensaku/kadai2.rbのようにファイル名を入力する
- ファイルの保存はC-x C-s
- 日本語入力のオンオフの切り替えはC-o
Mewについて
- emacsを起動する
- Escとxを押し,mewと入力しReturn(Escとxを押すことを,一般にM-xと表記します)%<--これでMewが起動します
- Mewを起動するとパスワードがたずねられるので入力しReturn
- 新着メールの確認およびパスワードを間違えた場合はiと入力しReturn
- メールを読む場合は,カーソルキー(矢印キー)で読みたいメールを選びReturn
- メールの新規作成はwと入力
- e-mailの本文にテキストファイルを読み込むには,新規送信メール画面の本文を記入するエリアにカーソルを移動し,Ctrl+x,iとすると,ミニバッファにInsert file: ~/と表示されるので,読み込みたいファイル名を入力する。
- プログラムの実行結果の貼り付けは,kterm上の出力結果部分をマウスで選択し,Mewの本文の貼り付け位置にカーソルを移動し,マウスの真ん中ボタンをクリックする
- メールの送信はC-c C-cと入力するか,もしくはメニューのsendアイコンをクリックする
- Mewを終了するにはqと入力
- emacsを終了する