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

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

地区,総数,農用地,森林
庄内地区,240511,43615,161624
最上地区,180362,18871,142018
村山地区,261914,37197,173400
置賜地区,249552,26600,191551

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

% ./ranking.rb
データファイルを指定して下さい。
実行例:
        % ./ranking.rb datafile.csv        総面積順に出力
        % ./ranking.rb -a datafile.csv     農用地面積順に出力
        % ./ranking.rb -f datafile.csv     森林面積順に出力
% ./ranking.rb area.csv
--地区---------総面積-------農用地-------森林---
  村山地区     261914        37197      173400
  置賜地区     249552        26600      191551
  庄内地区     240511        43615      161624
  最上地区     180362        18871      142018
./ranking.rb -a area.csv
--地区---------総面積-------農用地-------森林---
  庄内地区     240511        43615      161624
  村山地区     261914        37197      173400
  置賜地区     249552        26600      191551
  最上地区     180362        18871      142018
./ranking.rb -f area.csv
--地区---------総面積-------農用地-------森林---
  置賜地区     249552        26600      191551
  村山地区     261914        37197      173400
  庄内地区     240511        43615      161624
  最上地区     180362        18871      142018

ヒント1

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

area = Array.new
area << {"div"   => 地区名,
	 "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.csv        総面積順に出力
	% ./ranking.rb -a datafile.csv     農用地面積順に出力
	% ./ranking.rb -f datafile.csv     森林面積順に出力
"
  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
  :
  :
 (以下省略)

本日の目次