21
21
// MODULES //
22
22
23
23
var startsWith = require ( '@stdlib/string/starts-with' ) ;
24
+ var max = require ( '@stdlib/math/base/special/max' ) ;
25
+ var abs = require ( '@stdlib/math/base/special/abs' ) ;
26
+
27
+
28
+ // FUNCTIONS //
29
+
30
+ /**
31
+ * Checks if the completion is a fuzzy match for the input.
32
+ *
33
+ * A fuzzy match is determined by the number and order of matching characters, penalizing large distances between matches.
34
+ * A score above or equal to 0.8 indicates a match.
35
+ *
36
+ * @private
37
+ * @param {string } completion - The completion string.
38
+ * @param {string } input - The input string.
39
+ * @returns {boolean } - True if the completion is a fuzzy match for the input, false otherwise.
40
+ */
41
+ function fuzzyMatch ( completion , input ) {
42
+ var charPositions ;
43
+ var finalScore ;
44
+ var positions ;
45
+ var distance ;
46
+ var score ;
47
+ var index ;
48
+ var char ;
49
+ var i ;
50
+ var j ;
51
+
52
+ if ( startsWith ( completion , input ) ) {
53
+ return true ; // Return true for perfect matches
54
+ }
55
+
56
+ // Preprocess the completion string to get the positions of each character
57
+ positions = { } ;
58
+ for ( i = 0 ; i < completion . length ; i ++ ) {
59
+ char = completion [ i ] ;
60
+ if ( ! positions [ char ] ) {
61
+ positions [ char ] = [ ] ;
62
+ }
63
+ positions [ char ] . push ( i ) ;
64
+ }
65
+
66
+ score = 0 ;
67
+ index = 0 ;
68
+ for ( i = 0 ; i < input . length ; i ++ ) {
69
+ charPositions = positions [ input [ i ] ] ;
70
+ if ( ! charPositions ) {
71
+ continue ;
72
+ }
73
+
74
+ // Find the next position of the character that is greater than or equal to index
75
+ j = 0 ;
76
+ while ( j < charPositions . length && charPositions [ j ] < index ) {
77
+ j += 1 ;
78
+ }
79
+ if ( j === charPositions . length ) {
80
+ continue ;
81
+ }
82
+
83
+ distance = abs ( charPositions [ j ] - i ) ;
84
+ score += max ( 0 , 1 - ( distance * 0.25 ) ) ; // Subtract a penalty based on the distance between matching characters
85
+ index = charPositions [ j ] + 1 ;
86
+ }
87
+ finalScore = score / input . length ; // Calculate relative score
88
+
89
+ return finalScore >= 0.65 ;
90
+ }
24
91
25
92
26
93
// MAIN //
@@ -37,7 +104,7 @@ var startsWith = require( '@stdlib/string/starts-with' );
37
104
function filterByPrefix ( out , arr , str ) {
38
105
var i ;
39
106
for ( i = 0 ; i < arr . length ; i ++ ) {
40
- if ( startsWith ( arr [ i ] , str ) ) {
107
+ if ( fuzzyMatch ( arr [ i ] , str ) ) {
41
108
out . push ( arr [ i ] ) ;
42
109
}
43
110
}
0 commit comments