町域コンパレータ(基本コード)

日本郵便から配布されている郵便番号データでは、町域名が綺麗にソートされています。郵便番号の順序情報を利用して、町域をソートする町域コンパレータを作ってみました。
実用にあたっては、例外処理を追加することが必要ですが、例外処理をまだ書いていないので、かえって読解しやすいコードとなっているかもしれません。

the code

日本郵便から配布されている、「全国一括」の郵便番号データ(http://www.post.japanpost.jp/zipcode/dl/kogaki.html から入手できるもの)を展開した ken_all.csv を使用します。下のコードでは、このファイルを /Users/hfu/src/postal/ken_all.csv に置いています。このファイルにある順序情報をいったん全部メモリに読み込んで処理する形です。

#postal.rb
$KCODE = 'u'
require 'iconv'

class Choiki < Array
	@@data = Hash.new {|h, k| h[k] = {}}
	count = 0
	File.foreach('/Users/hfu/src/postal/ken_all.csv') {|l|
  	r = Iconv.conv('UTF-8', 'Shift_JIS', l).strip.gsub('"', '').split(',')
  	#print r.join(','), "\n"
  	(city_code, postal_code, choiki) = [r[0], r[2], r[8]]
  	next if /0000$/.match postal_code
  	choiki.sub!(/.*?/, '')
  	@@data[city_code][choiki] = count
		count += 1
		#p @data
	}
  
  def initialize(array)
  	super(array)
  end
  
  def <=>(other)
  	(self[0] <=> other[0]) == 0 ? (@@data[self[0]][self[1]] <=> @@data[other[0]][other[1]]) : (self[0] <=> other[0])
  end
end

if __FILE__ == $0
  p Choiki.new(["01104", "東米里"]) <=> Choiki.new(["01104", "菊水上町四条"])
  p [Choiki.new(["47381", "鳩間"]), Choiki.new(["47381", "波照間"])].sort
end

都道府県コード(及び郵便番号)も文字列として扱っていることに注意して下さい。これを実行すると、次のようになります。

$ ruby -Ku postal.rb 
1
[["47381", "波照間"], ["47381", "鳩間"]]

これを使えば、任意の町域データを日本郵便の順序にソートできる、はずです。