Module: JapaneseAddressParser::Normalize

Defined in:
lib/japanese_address_parser/normalize.rb,
sig/normalize.rbs

Overview

住所文字列を都道府県・市区町村・町字・番地へ正規化する(level 0-3)。

Constant Summary collapse

DEFAULT_LEVEL =

JS: defaultOption = { level: 8 }

Returns:

  • (Integer)
8
NUM =

番地正規化で使う「半角数字 or 漢数字」の交替(1 キャプチャグループ)。

Returns:

  • (String)
'([0-9]+|[〇一二三四五六七八九十百千]+)'
DASHES =

数字に隣接する横棒(ハイフン・マイナス・長音記号・罫線等)の文字クラス(上流 normalize.ts と同一)。

Returns:

  • (String)
'--﹣−‐⁃‑‒–—﹘―⎯⏤ーー─━'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.call(address, level: DEFAULT_LEVEL) ⇒ Object

JS: normalize(address, option)



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/japanese_address_parser/normalize.rb', line 36

def call(address, level: DEFAULT_LEVEL)
  other = NormalizeHelpers.prenormalize(address)

  # @type var pref: Data::SinglePrefecture?
  pref = nil
  # @type var city: Data::SingleCity?
  city = nil
  # @type var town: untyped
  town = nil
  # @type var point: NormalizeResultPoint?
  point = nil
  # @type var addr: String?
  addr = nil

  prefectures = CacheRegexes.get_prefectures
  api_version = prefectures.meta.updated
  pref_patterns = CacheRegexes.get_prefecture_regex_patterns(prefectures)
  same_named_patterns = CacheRegexes.get_same_named_prefecture_city_regex_patterns(prefectures)

  # 県名が省略されており市名がどこかの都道府県名と同じ場合(例: 千葉県千葉市)、県名を補完する。
  same_named_patterns.each do |prefecture_city, reg|
    regex = ::Regexp.new(reg)
    next unless other.match?(regex)

    other = other.sub(regex, prefecture_city) # JS: replace(new RegExp(reg), prefectureCity)(g 無し)
    break
  end

  # 都道府県名の正規化
  pref_patterns.each do |single_pref, pattern|
    match = other.match(::Regexp.new(pattern))
    next unless match

    pref = single_pref
    other = other[match[0].to_s.length..].to_s # 都道府県名以降の住所
    point = ResultPoint.prefecture_to_result_point(single_pref)
    break
  end

  unless pref
    # 都道府県名が省略されている。全都道府県の市区町村パターンから候補を集める。
    # @type var matched: Array[Hash[Symbol, untyped]]
    matched = []
    prefectures.data.each do |single_pref|
      city_patterns = CacheRegexes.get_city_regex_patterns(single_pref)
      other = other.strip
      city_patterns.each do |single_city, pattern|
        match = other.match(::Regexp.new(pattern))
        matched << { pref: single_pref, city: single_city, other: other[match[0].to_s.length..].to_s } if match
      end
    end

    if matched.length == 1
      pref = matched[0][:pref]
    else
      # 複数候補は町名まで正規化して判別する(例: 東京都府中市 と 広島県府中市)。
      matched.each do |candidate|
        normalized = normalize_town_name(candidate[:other], candidate[:pref], candidate[:city], api_version)
        next unless normalized

        pref = candidate[:pref]
        city = candidate[:city]
        town = normalized[:town]
        other = normalized[:other]
        point = ResultPoint.upgrade_point(point, ResultPoint.machi_aza_to_result_point(town))
      end
    end
  end

  if pref && level >= 2
    city_patterns = CacheRegexes.get_city_regex_patterns(pref)
    other = other.strip
    city_patterns.each do |single_city, pattern|
      match = other.match(::Regexp.new(pattern))
      next unless match

      city = single_city
      point = ResultPoint.upgrade_point(point, ResultPoint.city_to_result_point(single_city))
      other = other[match[0].to_s.length..].to_s # 市区町村名以降の住所
      break
    end
  end

  # 町丁目以降の正規化
  if pref && city && level >= 3
    normalized = normalize_town_name(other, pref, city, api_version)
    if normalized
      town = normalized[:town]
      other = normalized[:other]
      point = ResultPoint.upgrade_point(point, ResultPoint.machi_aza_to_result_point(town))
    end

    # town が取得できた場合にのみ、番地正規化を行う。
    other = normalize_addr(other) if town
  end

  other = PatchAddr.call(
    pref ? pref.prefecture_name : '',
    city ? city.city_name : '',
    town ? town.machi_aza_name : '',
    other
  )

  level_value = 0
  level_value += 1 if pref
  level_value += 1 if city
  level_value += 1 if town

  # JS: if (option.level <= 3 || level < 3) { return result }
  # metadata は VO に昇格しない生データの逃がし道(working_agreement §1-3)。
  if level <= 3 || level_value < 3
    return NormalizeResult.new(
      pref: pref ? pref.prefecture_name : nil,
      city: city ? city.city_name : nil,
      town: town ? town.machi_aza_name : nil,
      addr:,
      other:,
      point:,
      level: level_value,
      metadata: NormalizeResultMetadata.new(input: address, prefecture: Utils.remove_cities_from_prefecture(pref), city:, machi_aza: Utils.remove_extra_from_machi_aza(town), chiban: nil, rsdt: nil)
    )
  end

  # level 8(住居表示 rsdt / 地番 chiban)。ここに来るのは level_value == 3 かつ level >= 4 のとき。
  normalized_addr_part = normalize_addr_part(other, pref, city, town, api_version)
  # JS TODO: rsdt と地番を両方対応した時に両方返すけど、今は rsdt を優先する
  if normalized_addr_part[:rsdt]
    addr = normalized_addr_part[:rsdt].rsdt_to_string
    other = normalized_addr_part[:rest]
    point = ResultPoint.upgrade_point(point, ResultPoint.rsdt_or_chiban_to_result_point(normalized_addr_part[:rsdt]))
    level_value = 8
  elsif normalized_addr_part[:chiban]
    addr = normalized_addr_part[:chiban].chiban_to_string
    other = normalized_addr_part[:rest]
    point = ResultPoint.upgrade_point(point, ResultPoint.rsdt_or_chiban_to_result_point(normalized_addr_part[:chiban]))
    level_value = 8
  end

  NormalizeResult.new(
    pref: pref ? pref.prefecture_name : nil,
    city: city ? city.city_name : nil,
    town: town ? town.machi_aza_name : nil,
    addr:,
    other:,
    point:,
    level: level_value,
    metadata: NormalizeResultMetadata.new(
      input: address,
      prefecture: Utils.remove_cities_from_prefecture(pref),
      city:,
      machi_aza: Utils.remove_extra_from_machi_aza(town),
      chiban: normalized_addr_part[:chiban],
      rsdt: normalized_addr_part[:rsdt]
    )
  )
end

Instance Method Details

#self?.callNormalizeResult

Parameters:

  • address (String)
  • level: (Integer)

Returns:



9
# File 'sig/normalize.rbs', line 9

def self?.call: (String address, ?level: Integer) -> NormalizeResult

#self?.normalize_addrString

Parameters:

  • other (String)

Returns:

  • (String)


11
# File 'sig/normalize.rbs', line 11

def self?.normalize_addr: (String other) -> String

#self?.normalize_addr_partHash[Symbol, untyped]

Parameters:

  • addr (String)
  • pref (Object)
  • city (Object)
  • town (Object)
  • api_version (Integer)

Returns:

  • (Hash[Symbol, untyped])


12
# File 'sig/normalize.rbs', line 12

def self?.normalize_addr_part: (String addr, untyped pref, untyped city, untyped town, Integer api_version) -> Hash[Symbol, untyped]

#self?.normalize_town_name{ town: untyped, other: String }?

Parameters:

Returns:

  • ({ town: untyped, other: String }, nil)


10
# File 'sig/normalize.rbs', line 10

def self?.normalize_town_name: (String input, Data::SinglePrefecture pref, Data::SingleCity city, Integer api_version) -> { town: untyped, other: String }?