123456789_123456789_123456789_123456789_123456789_

Class: DidYouMean::TreeSpellChecker

Relationships & Source Files
Inherits: Object
Defined in: lib/did_you_mean/tree_spell_checker.rb

Overview

spell checker for a dictionary that has a tree structure, see doc/tree_spell_checker_api.md

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(dictionary:, separator: '/', augment: nil) ⇒ TreeSpellChecker

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 9

def initialize(dictionary:, separator: '/', augment: nil)
  @dictionary = dictionary
  @separator = separator
  @augment = augment
end

Instance Attribute Details

#augment (readonly)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 7

attr_reader :dictionary, :separator, :augment

#dictionary (readonly)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 7

attr_reader :dictionary, :separator, :augment

#separator (readonly)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 7

attr_reader :dictionary, :separator, :augment

Instance Method Details

#correct(input)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 15

def correct(input)
  plausibles = plausible_dimensions(input)
  return fall_back_to_normal_spell_check(input) if plausibles.empty?

  suggestions = find_suggestions(input, plausibles)
  return fall_back_to_normal_spell_check(input) if suggestions.empty?

  suggestions
end

#correct_element(names, element) (private)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 93

def correct_element(names, element)
  return names if names.size == 1

  str = normalize(element)

  return [str] if names.include?(str)

  ::DidYouMean::SpellChecker.new(dictionary: names).correct(str)
end

#dictionary_without_leaves

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 25

def dictionary_without_leaves
  @dictionary_without_leaves ||= dictionary.map { |word| word.split(separator)[0..-2] }.uniq
end

#dimensions

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 33

def dimensions
  @dimensions ||= tree_depth.times.map do |index|
                    dictionary_without_leaves.map { |element| element[index] }.compact.uniq
                  end
end

#fall_back_to_normal_spell_check(input) (private)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 68

def fall_back_to_normal_spell_check(input)
  return [] unless augment

  ::DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input)
end

#find_ideas(paths, leaf) (private)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 74

def find_ideas(paths, leaf)
  paths.flat_map do |path|
    names = find_leaves(path)
    ideas = correct_element(names, leaf)

    ideas_to_paths(ideas, leaf, names, path)
  end.compact
end

#find_leaves(path)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 39

def find_leaves(path)
  path_with_separator = "#{path}#{separator}"

  dictionary
    .select {|str| str.include?(path_with_separator) }
    .map {|str| str.gsub(path_with_separator, '') }
end

#find_suggestions(input, plausibles) (private)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 60

def find_suggestions(input, plausibles)
  states = plausibles[0].product(*plausibles[1..-1])
  paths  = possible_paths(states)
  leaf   = input.split(separator).last

  find_ideas(paths, leaf)
end

#ideas_to_paths(ideas, leaf, names, path) (private)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 83

def ideas_to_paths(ideas, leaf, names, path)
  if ideas.empty?
    nil
  elsif names.include?(leaf)
    ["#{path}#{separator}#{leaf}"]
  else
    ideas.map {|str| "#{path}#{separator}#{str}" }
  end
end

#normalize(str) (private)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 103

def normalize(str)
  str.downcase!
  str.tr!('@', ' ') if str.include?('@')
  str
end

#plausible_dimensions(input)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 47

def plausible_dimensions(input)
  input.split(separator)[0..-2]
    .map
    .with_index { |element, index| correct_element(dimensions[index], element) if dimensions[index] }
    .compact
end

#possible_paths(states)

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 54

def possible_paths(states)
  states.map { |state| state.join(separator) }
end

#tree_depth

[ GitHub ]

  
# File 'lib/did_you_mean/tree_spell_checker.rb', line 29

def tree_depth
  @tree_depth ||= dictionary_without_leaves.max { |a, b| a.size <=> b.size }.size
end