並べ替えプログラムの完成イメージ

データファイルとして以下のものを用意する。
area.dat

鶴岡市	141479	67147	74332
酒田市	116234	55213	61021
三川町	7953	3841	4112
遊佐町	16685	7846	8839
庄内町	24304	11552	12752

左から順に、市町村名、総面積、農用地面積、森林面積である。 これを読み込んで実行すると、以下のようになる

% ./ranking.rb
データファイルを指定して下さい。
実行例:
        % ./ranking.rb datafile.dat        総面積順に出力
        % ./ranking.rb -a datafile.dat     農用地面積順に出力
        % ./ranking.rb -f datafile.dat     森林面積順に出力
% ./ranking.rb area.dat
--地区---------総面積-------農用地-------森林---
    鶴岡市     141479        67147       74332
    酒田市     116234        55213       61021
    庄内町      24304        11552       12752
    遊佐町      16685         7846        8839
    三川町       7953         3841        4112
./ranking.rb -a area.dat
--地区---------総面積-------農用地-------森林---
    鶴岡市     141479        67147       74332
    酒田市     116234        55213       61021
    庄内町      24304        11552       12752
    遊佐町      16685         7846        8839
    三川町       7953         3841        4112
./ranking.rb -f area.dat
--地区---------総面積-------農用地-------森林---
    鶴岡市     141479        67147       74332
    酒田市     116234        55213       61021
    庄内町      24304        11552       12752
    遊佐町      16685         7846        8839
    三川町       7953         3841        4112

ヒント1

地区名と、その面積を読み取る部分では、配列変数 area を用意して、

area = Array.new
area << {"place" => 地区名,
	 "total" => 総面積値,
	 "farm"  => 農用地面積値,
	 "forest"=> 森林面積値}

という風に代入を行なうとよい。 並べ替える部分は以下のようになるだろう。

for i in area.sort_by{|x| x[比較したいキー]}.reverse
  ……
end

ヒント2

実行例では -a-f でソート基準を 変更するようになっている。プログラムの引数にハイフンで始まる文字を 指定して動きを変えることはよく利用される。この場合 -a-fオプションという。ARGV 配列を 先頭から調べて行き,あらかじめ決めたオプションに一致したら動きを変えるよ うにする。完成形プログラムの前半は以下のようになる。

if ARGV[0] == nil
  STDERR.print "データファイルを指定して下さい。
実行例:
	% ./ranking.rb datafile.dat        総面積順に出力
	% ./ranking.rb -a datafile.dat     農用地面積順に出力
	% ./ranking.rb -f datafile.dat     森林面積順に出力
"
  exit 1
end

sortby = "total"		# デフォルトは総面積でソート
while /^-/ =~ ARGV[0]		# ハイフンで始まる間繰り返す
  if ARGV[0] == "-a"
    (ソート規準を農用地にする)
  elsif ARGV[0] == "-f"
    (ソート規準を森林にする)
  else
    break
  end
  ARGV.shift
end

area = Array.new
  :
  :
 (以下省略)

本日の目次