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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# File 'lib/goto_string.rb', line 20
def Matcher.match( pattern, candidates, &block )
pattern.gsub! "'",""
pattern.downcase!
matches = []
candidates.each do |candidate_obj|
if block_given?
candidate = yield candidate_obj
else
candidate = candidate_obj
end
candidate = candidate.downcase
pat = pattern.dup.unpack('c*')
can = candidate.dup
pattern_len = pattern.size
matched_strings = []
current_pos = 0
consecutive = 0
sum_positions = 0
while (s=pat.shift) && (index=can.index(s))
current_pos += index+1
can = can[index+1..-1]
if (0 != index || matched_strings.empty?)
matched_strings << [s.chr,current_pos-1]
else
matched_strings.last[0] << s.chr
end
s = nil
end
next if !pat.empty? || s
sum_positions = 0
consecutive = 0
matched_strings.each do |m|
ms = m[0].size
consecutive += (ms-1)*(ms-1)
sum_positions += (m[1]+m[1]+ms-1)*ms/2
end
score_position = ((pattern_len.to_f)*(pattern_len.to_f+1)/2.0) / sum_positions
score_consecutive = consecutive.to_f / (pattern_len*pattern_len)
matches <<[ candidate_obj, candidate, ( score_consecutive * @@weight_consecutive + score_position *@@weight_positional)/(@@weight_consecutive+@@weight_positional), matched_strings]
end
matches.sort do |a,b|
if a[2]<b[2]
1
elsif a[2]>b[2]
-1
else
a[1].size <=> b[1].size
end
end
end
|