データファイルとして以下のものを用意する。
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
地区名と、その面積を読み取る部分では、配列変数
area
を用意して、
area = Array.new area << {"div" => 地区名, "total" => 総面積値, "farm" => 農用地面積値, "forest"=> 森林面積値}
という風に代入を行なうとよい。 並べ替える部分は以下のようになるだろう。
for i in area.sort_by{|x| x[比較したいキー]}.reverse …… end
実行例では -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 : : (以下省略)