Skip to content

Commit d769db6

Browse files
Merge pull request #36 from Shopify/region_lookup_by_code_using_hash_2023-11-07
Improve performance by using hash table for by-code region lookup
2 parents eda16cf + bd2f2b8 commit d769db6

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
2626

2727
- Add region name alternates [#32](https://github.com/Shopify/worldwide/pull/32)
2828
- Cache `Region#parent_name` [#33](https://github.com/Shopify/worldwide/pull/33)
29+
- Use hash tables to look up regions by code [#36](https://github.com/Shopify/worldwide/pull/36)
2930

3031
---
3132

lib/worldwide/regions.rb

+3-11
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class << self
1616
end
1717

1818
def initialize
19-
@regions = RegionsLoader.new.load_regions
19+
@regions, @regions_by_cldr_code, @regions_by_iso_code = RegionsLoader.new.load_regions
2020
end
2121

2222
def all
@@ -29,17 +29,9 @@ def region(cldr: nil, code: nil, name: nil)
2929
end
3030

3131
result = if cldr
32-
search_code = cldr.to_s.upcase
33-
34-
@regions.find do |r|
35-
r.send(:answers_to_cldr_code, search_code)
36-
end
32+
@regions_by_cldr_code[cldr.to_s.upcase]
3733
elsif code
38-
search_code = code.to_s.upcase
39-
40-
@regions.find do |r|
41-
r.send(:answers_to_iso_code, search_code) || r.alpha_three == search_code || r.numeric_three == search_code
42-
end
34+
@regions_by_iso_code[code.to_s.upcase]
4335
else # search by name
4436
search_name = name.upcase
4537

lib/worldwide/regions_loader.rb

+32-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ class RegionsLoader
99
WORLD_CODE = "001" # UN code for the whole world
1010

1111
def load_regions
12+
@regions_by_cldr_code = {}
13+
@regions_by_iso_code = {}
14+
1215
# Load country/region definitions out of the db/data/regions/??.yml files
1316
@regions = Dir["#{Worldwide::Paths::REGIONS_ROOT}/*.yml"].map do |filename|
1417
load_territory(filename)
@@ -25,11 +28,39 @@ def load_regions
2528

2629
construct_unknown
2730

28-
@regions.freeze
31+
@regions.each do |region|
32+
construct_lookup_info(region)
33+
end
34+
35+
[@regions.freeze, @regions_by_cldr_code, @regions_by_iso_code]
2936
end
3037

3138
private
3239

40+
def construct_lookup_info(region)
41+
pc = region.send(:parent_country)
42+
43+
# Remember CLDR code(s) for later use during lookup
44+
45+
search_code = region.cldr_code.to_s.upcase
46+
@regions_by_cldr_code[search_code] = region if Util.present?(search_code)
47+
48+
@regions_by_cldr_code["#{pc.cldr_code.upcase}#{search_code}"] = region if Util.present?(pc&.cldr_code)
49+
50+
# Remember ISO 3166 code(s) for later use during lookup
51+
52+
iso_code = region.iso_code
53+
@regions_by_iso_code[iso_code] = region if Util.present?(iso_code)
54+
55+
@regions_by_iso_code["#{pc.iso_code}-#{iso_code}"] = region if Util.present?(pc)
56+
57+
alpha_three = region.alpha_three
58+
@regions_by_iso_code[alpha_three] = region if Util.present?(alpha_three)
59+
60+
numeric_three = region.numeric_three
61+
@regions_by_iso_code[numeric_three] = region if Util.present?(numeric_three)
62+
end
63+
3364
def apply_hierarchy(parent:, code:, children:)
3465
current_region = find_region(code: code)
3566
if current_region.nil?

0 commit comments

Comments
 (0)