@@ -9,9 +9,11 @@ export default function suggestionList(
9
9
options : $ReadOnlyArray < string > ,
10
10
) : Array < string > {
11
11
const optionsByDistance = Object . create ( null ) ;
12
+ const lexicalDistance = new LexicalDistance ( input ) ;
13
+
12
14
const inputThreshold = input . length / 2 ;
13
15
for ( const option of options ) {
14
- const distance = lexicalDistance ( input , option ) ;
16
+ const distance = lexicalDistance . measure ( option ) ;
15
17
const threshold = Math . max ( inputThreshold , option . length / 2 , 1 ) ;
16
18
if ( distance <= threshold ) {
17
19
optionsByDistance [ option ] = distance ;
@@ -36,50 +38,60 @@ export default function suggestionList(
36
38
* of 1.
37
39
*
38
40
* This distance can be useful for detecting typos in input or sorting
39
- *
40
- * @param {string } a
41
- * @param {string } b
42
- * @return {int } distance in number of edits
43
41
*/
44
- function lexicalDistance ( aStr , bStr ) {
45
- if ( aStr === bStr ) {
46
- return 0 ;
42
+ class LexicalDistance {
43
+ _input : string ;
44
+ _inputLowerCase : string ;
45
+ _cells : Array < Array < number >> ;
46
+
47
+ constructor ( input : string ) {
48
+ this . _input = input ;
49
+ this . _inputLowerCase = input . toLowerCase ( ) ;
50
+ this . _cells = [ ] ;
47
51
}
48
52
49
- const d = [ ] ;
50
- const a = aStr . toLowerCase ( ) ;
51
- const b = bStr . toLowerCase ( ) ;
52
- const aLength = a . length ;
53
- const bLength = b . length ;
53
+ measure ( option : string ) : number {
54
+ if ( this . _input === option ) {
55
+ return 0 ;
56
+ }
54
57
55
- // Any case change counts as a single edit
56
- if ( a === b ) {
57
- return 1 ;
58
- }
58
+ const optionLowerCase = option . toLowerCase ( ) ;
59
59
60
- for ( let i = 0 ; i <= aLength ; i ++ ) {
61
- d [ i ] = [ i ] ;
62
- }
60
+ // Any case change counts as a single edit
61
+ if ( this . _inputLowerCase === optionLowerCase ) {
62
+ return 1 ;
63
+ }
63
64
64
- for ( let j = 1 ; j <= bLength ; j ++ ) {
65
- d [ 0 ] [ j ] = j ;
66
- }
65
+ const d = this . _cells ;
66
+ const a = optionLowerCase ;
67
+ const b = this . _inputLowerCase ;
68
+ const aLength = a . length ;
69
+ const bLength = b . length ;
70
+
71
+ for ( let i = 0 ; i <= aLength ; i ++ ) {
72
+ d [ i ] = [ i ] ;
73
+ }
67
74
68
- for ( let i = 1 ; i <= aLength ; i ++ ) {
69
75
for ( let j = 1 ; j <= bLength ; j ++ ) {
70
- const cost = a [ i - 1 ] === b [ j - 1 ] ? 0 : 1 ;
76
+ d [ 0 ] [ j ] = j ;
77
+ }
71
78
72
- d [ i ] [ j ] = Math . min (
73
- d [ i - 1 ] [ j ] + 1 ,
74
- d [ i ] [ j - 1 ] + 1 ,
75
- d [ i - 1 ] [ j - 1 ] + cost ,
76
- ) ;
79
+ for ( let i = 1 ; i <= aLength ; i ++ ) {
80
+ for ( let j = 1 ; j <= bLength ; j ++ ) {
81
+ const cost = a [ i - 1 ] === b [ j - 1 ] ? 0 : 1 ;
77
82
78
- if ( i > 1 && j > 1 && a [ i - 1 ] === b [ j - 2 ] && a [ i - 2 ] === b [ j - 1 ] ) {
79
- d [ i ] [ j ] = Math . min ( d [ i ] [ j ] , d [ i - 2 ] [ j - 2 ] + cost ) ;
83
+ d [ i ] [ j ] = Math . min (
84
+ d [ i - 1 ] [ j ] + 1 ,
85
+ d [ i ] [ j - 1 ] + 1 ,
86
+ d [ i - 1 ] [ j - 1 ] + cost ,
87
+ ) ;
88
+
89
+ if ( i > 1 && j > 1 && a [ i - 1 ] === b [ j - 2 ] && a [ i - 2 ] === b [ j - 1 ] ) {
90
+ d [ i ] [ j ] = Math . min ( d [ i ] [ j ] , d [ i - 2 ] [ j - 2 ] + cost ) ;
91
+ }
80
92
}
81
93
}
82
- }
83
94
84
- return d [ aLength ] [ bLength ] ;
95
+ return d [ aLength ] [ bLength ] ;
96
+ }
85
97
}
0 commit comments