module Jipcode::AddressLocator
Constants
- GAIKU_HYOUJI
丁目・番・号・地割・番地をハイフンに置換する
1丁目2番3号 -> 1-2-3 1丁目2番3 -> 1-2-3 1丁目2-3 -> 1-2-3 1丁目2番 -> 1-2 1地割2番地 -> 1-2 1丁目2番地の3 -> 1-2-3 etc..
@private @see ja.wikipedia.org/wiki/%E4%BD%8F%E5%B1%85%E8%A1%A8%E7%A4%BA
- INDEX_PATH
- INDEX_VERSION_FILE
- VERSION
Public Class Methods
create_index!()
click to toggle source
Create index files by Jipcode
data.
# File lib/jipcode/address_locator/indexer.rb, line 19 def self.create_index! refresh_index_dir index = collect_index export_index(index) File.open(INDEX_VERSION_FILE, 'w') do |f| f.write(Jipcode::VERSION) end end
exist_latest_index?()
click to toggle source
Make sure Jipcode
version and index version are the same. @return [Boolean] result
# File lib/jipcode/address_locator/indexer.rb, line 11 def self.exist_latest_index? return false unless File.exist?(INDEX_VERSION_FILE) version = File.read(INDEX_VERSION_FILE) version == Jipcode::VERSION end
locate(search_address)
click to toggle source
Locate zipcode data by address @param [String] search_address @return [Array<Hash>] zipcode data
# File lib/jipcode/address_locator/locator.rb, line 13 def self.locate(search_address) normalized = normalize_address(search_address) find_by_address(normalized) .map { |address| calc_and_add_distance!(address, normalized) } .sort_by { |address| address['distance'] } .reverse end
normalize_address(raw_address)
click to toggle source
Normalize japanese address for search. @example
Jipcode::AddressLocator.normalize_address('稲穂県ミドリ市一番町一丁目2の3番') # => '稲穂県ミドリ市一番町1-2-3'
@param [String] raw_address @return [String] normalized address
# File lib/jipcode/address_locator/normalizer.rb, line 11 def self.normalize_address(raw_address) zenkaku2hankaku(raw_address) .yield_self { |address| kansuji2hankaku(address) } .yield_self { |address| jukyohyouji2hyphen(address) } end
Private Class Methods
calc_and_add_distance!(address, search_address)
click to toggle source
@private
# File lib/jipcode/address_locator/locator.rb, line 38 def self.calc_and_add_distance!(address, search_address) distance = JaroWinkler.distance(address['normalized_address'], search_address) address['distance'] = distance address end
collect_index()
click to toggle source
@private
# File lib/jipcode/address_locator/indexer.rb, line 38 def self.collect_index index = 47.times.each_with_object({}) { |item, memo| memo[item + 1] = []; } Dir.glob("#{ZIPCODE_PATH}/*.csv").each do |file_name| CSV.read(file_name).each do |row| _zipcode, prefecture_name, city, town = row row << normalize_address("#{prefecture_name}#{city}#{town}") prefecture_code = extract_prefecture_code(prefecture_name) index[prefecture_code] << row end end index end
export_index(index)
click to toggle source
@private
# File lib/jipcode/address_locator/indexer.rb, line 54 def self.export_index(index) index.each do |prefecture_code, rows| rows.sort_by! { |row| [row[0], row[2], row[3]] } CSV.open("#{INDEX_PATH}/#{prefecture_code}.csv", 'wb') do |csv| csv << %w[zipcode prefecture_name city town normalized_address] rows.each { |row| csv << row } end end end
extract_prefecture_code(address)
click to toggle source
@private
# File lib/jipcode/address_locator/helper.rb, line 6 def self.extract_prefecture_code(address) prefecture_name = address.match(/\A(#{prefecture_names.join('|')})/).to_s PREFECTURE_CODE.invert[prefecture_name] end
find_by_address(search_address)
click to toggle source
@private
# File lib/jipcode/address_locator/locator.rb, line 23 def self.find_by_address(search_address) prefecture_code = extract_prefecture_code(search_address) path = "#{INDEX_PATH}/#{prefecture_code}.csv" return [] if prefecture_code.nil? CSV.read(path, headers: true).select do |row| address = row['normalized_address'] # 長いほうが短い方に含まれてるか判別 long = [address, search_address].max short = [address, search_address].min long.start_with?(short) end end
jukyohyouji2hyphen(string)
click to toggle source
# File lib/jipcode/address_locator/normalizer.rb, line 52 def self.jukyohyouji2hyphen(string) string.gsub(/\d(#{GAIKU_HYOUJI.join('|')})/) { |match| match.gsub(/(#{GAIKU_HYOUJI.join('|')})/, '-') } .gsub(/-$/, '') end
kansuji2hankaku(string)
click to toggle source
住居表示の漢数字を半角数字に置き換える @private
# File lib/jipcode/address_locator/normalizer.rb, line 26 def self.kansuji2hankaku(string) # 漢数字は「丁目」の前に使われてるもののみを半角にする string.gsub(/[一二三四五六七八九十]+丁目/) do |match| match.tr('一二三四五六七八九', '1-9') # TODO: 十丁目 -> 10、十三丁目 -> 13 二十丁目 -> 20 end end
prefecture_names()
click to toggle source
@private
# File lib/jipcode/address_locator/helper.rb, line 12 def self.prefecture_names PREFECTURE_CODE.values end
refresh_index_dir()
click to toggle source
@private
# File lib/jipcode/address_locator/indexer.rb, line 32 def self.refresh_index_dir FileUtils.rm_rf(INDEX_PATH) if File.exist?(INDEX_PATH) Dir.mkdir(INDEX_PATH) end
zenkaku2hankaku(string)
click to toggle source
全角数字ハイフン→半角数字ハイフン @private
# File lib/jipcode/address_locator/normalizer.rb, line 19 def self.zenkaku2hankaku(string) string.tr('0-9', '0-9') .tr('–−', '-') end