-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfind_unknown_value.rb
54 lines (42 loc) · 1.62 KB
/
find_unknown_value.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# frozen_string_literal: true
require 'damerau-levenshtein'
BEST_GUESS_DISTANCE = 10
# Performs Levenshtein distance and partial match detection on unknown_value within list of known_values.
def find_unknown_value(known_values, unknown_value)
# find levenshtein best guess
lev_best_guess = perform_levenshtein(unknown_value, known_values)
# levenshtein won't find partial matches
# (e.g. if we are looking for 'max', we expect 'max_bright' to be a possible guess)
# so look for partials in command list
possible_partials = find_partials(unknown_value, known_values)
# don't add levenshtein guess if already in partial list
possible_partials.append(lev_best_guess) if !possible_partials.include?(lev_best_guess) && lev_best_guess != ''
possible_partials
end
def find_partials(unknown_command, known_commands)
possible = []
known_commands.each do |command|
possible.append(command) if command.include? unknown_command
end
possible
end
# returns a single best guess or empty string if distance is too high
def perform_levenshtein(unknown_command, known_commands)
dl = DamerauLevenshtein
best_guess = ''
best_guess_distance = -1
known_commands.each do |command|
guess_distance = dl.distance(command, unknown_command)
next unless best_guess.empty? || guess_distance <= best_guess_distance
best_guess = command
best_guess_distance = guess_distance
next
end
# Return empty string if best_guess_distance is really high
# How helpful would it be to provide a suggested match to 'ashpoijeiphasdrtqadjh' ?
if best_guess_distance < BEST_GUESS_DISTANCE
best_guess
else
''
end
end