(7)11/09の授業内容

  1. ハッシュ
  2. これまでは配列を繰り返し使用してきました。ハッシュについて話をする前に、まず配列の確認をしておきましょう。配列は、インデックスを用いて値を順次代入したり、取り出したりするために使用してきました。以下ではデータが数字の場合と文字列の場合を両方とも示します。

    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を入力するとどのようになるか調べてみよう。

  3. ハッシュへの値の追加
  4. 配列にデータが格納できるのと同様に、ハッシュにもデータを格納することができます。ただし、この際には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
    親会社(登録終了の場合は おしまい と入力):西武
    チーム名:ライオンズ
    親会社(登録終了の場合は おしまい と入力):オリックス
    チーム名:バファローズ
    親会社(登録終了の場合は おしまい と入力):読売
    チーム名:ジャイアンツ
    親会社(登録終了の場合は おしまい と入力):ソフトバンク
    チーム名:ホークス
    親会社(登録終了の場合は おしまい と入力):阪神
    チーム名:タイガース
    親会社(登録終了の場合は おしまい と入力):おしまい
    {"西武"=>"ライオンズ", "オリックス"=>"バファローズ", "読売"=>"ジャイアンツ",
     "ソフトバンク"=>"ホークス", "阪神"=>"タイガース"}

  5. ハッシュから値を取り出す
  6. ハッシュから値を取り出す方法について、配列と比較をしながら見てみましょう。いずれもレジにてレシートを作成するプログラムを想定しています。購入したものと金額はバーコードにより読み取り済みであり、配列、ハッシュに入力されているものとします。

    配列を使用した場合は下記の通りとなります(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番を作成してください。

  1. 授業中に使用したreceipt-hash.rbでは、既に購入品名と金額がハッシュに代入されていた。これを改良し、品物と金額を順番に入力することでレシートを表示するプログラムを作成してください(9点満点)
  2. 1番と同じだが、品物と金額を順番に入力するのではなく、これらを記述したテキストファイルから読み込んでレシートを表示するプログラムを作成してください。このプログラムを作成するためにはopenメソッドと正規表現を使用する必要があります(10点満点)
  3. 授業中に使用したkeroro.rbを見本に、自分の好きなデータをハッシュに代入しておき、あとから検索できるプログラムを作成してください。検索できるデータは誕生石、12星座と誕生日、アニメのキャラクタと声優、山と標高、国と首都など好きなものを選んでください。他の人とは違うもの、楽しいものが望ましい。最低でも10個以上のデータを作ること(ハッシュを10個ではなく、データが10個以上代入されているハッシュ変数を1つ作るということ)(8点満点)

作成したプログラムや実行結果をメールでnaoya@e.koeki-u.ac.jp宛に送る

課題の提出期限は11月15日(火)23:59までです


メール送信時の注意

説明のポイント(1番と2番):ハッシュとは何か、ハッシュへの値の代入、ハッシュからの値の取り出しの3点について説明がなされていること(2番を選んだ人は正規表現とopenメソッドについても説明すること)。単にWEBページをコピーペーストしたものは減点対象とする

説明のポイント(3番):使用したデータについて、ハッシュとは何か、プログラムの各行の説明を行うこと。単にWEBページをコピーペーストしたものは減点対象とする

レポート採点基準(1番と2番):期限内提出(2点)、プログラムの正誤(2〜3点)、レシートの見栄え(1点)、説明(3点)、指示通りにメールを送っているか(1点)

レポート採点基準(3番):期限内提出(2点)、プログラムの正誤(2点)、説明(3点)、指示通りにメールを送っているか(1点)

Tips

emacsについて

Mewについて