Class: BBLib::FuzzyMatcher

Inherits:
LazyClass show all
Defined in:
lib/string/fuzzy_matcher.rb

Instance Method Summary collapse

Methods inherited from LazyClass

#initialize, #serialize

Methods included from Hooks

#add_after_hook, #add_before_hook, #after, #after_hooked_methods, #after_hooks, #after_hooks_for, #before, #before_hooked_methods, #before_hooks, #before_hooks_for, #method_added

Constructor Details

This class inherits a constructor from BBLib::LazyClass

Instance Method Details

#algorithmsObject



43
44
45
# File 'lib/string/fuzzy_matcher.rb', line 43

def algorithms
  @algorithms.keys
end

#best_match(a, b) ⇒ Object

Returns the best match from array b to string a based on percent.



27
28
29
# File 'lib/string/fuzzy_matcher.rb', line 27

def best_match a, b
  similarities(a, b).max_by{ |k, v| v}[0]
end

#match?(a, b) ⇒ Boolean

Checks to see if the match percentage between Strings a and b are equal to or greater than the threshold.

Returns:

  • (Boolean)


22
23
24
# File 'lib/string/fuzzy_matcher.rb', line 22

def match? a, b
  similarity(a, b) >= @threshold.to_f
end

#set_weight(algorithm, weight) ⇒ Object



38
39
40
41
# File 'lib/string/fuzzy_matcher.rb', line 38

def set_weight algorithm, weight
  return nil unless @algorithms.include? algorithm
  @algorithms[algorithm][:weight] = BBLib.keep_between(weight, 0, nil)
end

#similarities(a, b, sort: false) ⇒ Object

Returns a hash of array ‘b’ with the percentage match to a. If sort is true, the hash is sorted desc by match percent.



32
33
34
35
36
# File 'lib/string/fuzzy_matcher.rb', line 32

def similarities a, b, sort: false
  matches = Hash.new
  [b].flatten.each{ |m| matches[m] = self.similarity(a, m) }
  sort ? matches.sort_by{ |k, v| v }.reverse.to_h : matches
end

#similarity(a, b) ⇒ Object

Calculates a percentage match between string a and string b.



10
11
12
13
14
15
16
17
18
19
# File 'lib/string/fuzzy_matcher.rb', line 10

def similarity a, b
  prep_strings a, b
  return 100.0 if @a == @b
  score, total_weight = 0, @algorithms.map{|alg, v| v[:weight] }.inject{ |sum, w| sum+=w }
  @algorithms.each do |algo, vals|
    next unless vals[:weight] > 0
    score+= @a.send(vals[:signature], @b) * vals[:weight]
  end
  score / total_weight
end