Module: Utilities::PersonNameMatch
- Defined in:
- lib/utilities/person_name_match.rb
Class Method Summary collapse
- .normalize(name) ⇒ Object private
-
.score_first_name_match(person_first_name, parsed_first_name) ⇒ Object
Score how closely a stored first name matches a parsed first name.
-
.score_last_name_match(person_last_name, parsed_last_name) ⇒ Object
Score how closely a stored last name matches a parsed last name.
-
.score_match(person_first_name, person_last_name, parsed_first_name, parsed_last_name) ⇒ Object
Combined score: last name weighted 10x over first name.
-
.sort_by_match(people, parsed_first_name, parsed_last_name) ⇒ Object
Sort people by descending match score against the parsed name.
Class Method Details
.normalize(name) ⇒ Object (private)
52 53 54 |
# File 'lib/utilities/person_name_match.rb', line 52 def self.normalize(name) (name || '').downcase.strip.gsub(/\s+/, ' ') end |
.score_first_name_match(person_first_name, parsed_first_name) ⇒ Object
Score how closely a stored first name matches a parsed first name. Parts are compared positionally: 2 points for exact word match, 1 for matching initial.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/utilities/person_name_match.rb', line 5 def self.score_first_name_match(person_first_name, parsed_first_name) p_parts = normalize(parsed_first_name).gsub('.', ' ').split.reject(&:empty?) s_parts = normalize(person_first_name).gsub('.', ' ').split.reject(&:empty?) return 0 if p_parts.empty? return -1 if s_parts.empty? score = 0 [p_parts.length, s_parts.length].min.times do |i| if p_parts[i] == s_parts[i] score += 2 elsif p_parts[i][0] == s_parts[i][0] score += 1 end end score end |
.score_last_name_match(person_last_name, parsed_last_name) ⇒ Object
Score how closely a stored last name matches a parsed last name. 2 points per word in common.
26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/utilities/person_name_match.rb', line 26 def self.score_last_name_match(person_last_name, parsed_last_name) p_words = normalize(parsed_last_name).split.to_set s_words = normalize(person_last_name).split.to_set return 0 if p_words.empty? return -1 if s_words.empty? score = 0 p_words.each { |w| score += 2 if s_words.include?(w) } score end |
.score_match(person_first_name, person_last_name, parsed_first_name, parsed_last_name) ⇒ Object
Combined score: last name weighted 10x over first name.
39 40 41 42 |
# File 'lib/utilities/person_name_match.rb', line 39 def self.score_match(person_first_name, person_last_name, parsed_first_name, parsed_last_name) score_last_name_match(person_last_name, parsed_last_name) * 10 + score_first_name_match(person_first_name, parsed_first_name) end |
.sort_by_match(people, parsed_first_name, parsed_last_name) ⇒ Object
Sort people by descending match score against the parsed name. people must respond to #first_name and #last_name.
46 47 48 49 50 |
# File 'lib/utilities/person_name_match.rb', line 46 def self.sort_by_match(people, parsed_first_name, parsed_last_name) people.sort_by do |person| -score_match(person.first_name, person.last_name, parsed_first_name, parsed_last_name) end end |