検索機能の実装

データをプログラム中の変数に取り込んだだけでは 情報を利用できない。利用者に提供するためには, 必要なものを絞り込んで提示する機能が必要である。

先述の例の履修科目をハッシュ化したハッシュで保持したものから, 利用者が必要とするものを選んで出力するものを作成する。

ハッシュや配列からの絞り込み

ハッシュあるいは配列に複数の要素が入っているときに, その中からある一定の条件を満たしたもののみに選別するには select メソッドを利用する。ハッシュの持つ select メソッドは 配列の持つ select メソッドとほぼ同様の記法だが,ブロックに対する引数を2つにし, 各々にキーと値を受け取る形式にする。

db-hash.rb で読み取った値のうち,「開講時期」が "前期" であるものを選択するには以下のようにする。

# db-hash.rbの続きから
db = db.select {|kamoku, hash| hash["開講時期"] == "前期"}

selectメソッドによる絞り込みでは,文字列比較だけでなく 正規表現マッチや数値比較も使える。 これらの絞り込みを繰り返すことで複合条件の指定もできる。 以下の例は,開講時期と担当教員での絞り込みを正規表現マッチで行ない, 該当するもののみを出力するプログラムである。

db-search.rb

#!/usr/koeki/bin/ruby
# coding: utf-8

# データファイルが別の文字コードかもしれないので kconv の toutf8 メソッドを
# 用いて utf-8 に統一して正規表現マッチを行なう
require 'kconv'

db = {}
open("syllabus.txt", "r") do |df|
  while line = df.gets
    line = line.toutf8
    if /^科目名:\s*(.*)/ =~ line	# 行頭「科目名:」空白(任意文字列)
      key = $1
      db[key] = Hash.new
    elsif /^(\S+):\s*(.*)/ =~ line	# 行頭(非空白続き):空白(任意文字列)
      db[key][$1] = $2
    end
  end
end

STDERR.print("開講時期は(指定なしの場合は空で)?: ")
term = gets.chomp
STDERR.print("担当教員は(指定なしの場合は空で)?: ")
whom = gets.chomp

if term > ""			# 開講時期指定に何か文字列を入れたなら
  ptn = Regexp.new(term)	# 文字列を正規表現に変換
  db = db.select {|k, v| ptn =~ v["開講時期"]}
end
if whom > ""			# 担当教員指定に何か文字列を入れたなら
  ptn = Regexp.new(whom)	# 文字列を正規表現に変換
  db = db.select {|k, v| ptn =~ v["担当教員"]}
end

puts("【該当科目一覧】")
db.each {|k, h|
  printf("%s %sの情報 %s\n", "="*20, k, "="*20)
  h.each {|key, value|
    printf("%s: %s\n", key, value)
  }
}

本日の目次