@@ -90,91 +90,97 @@ function printTab(nb) {
90
90
* algorithm should not matter to the caller of the methods, which is why it is not noted in the
91
91
* documentation.
92
92
*/
93
- let editDistanceCurrent = [ ] ;
94
- let editDistancePrev = [ ] ;
95
- let editDistancePrevPrev = [ ] ;
96
- function editDistance ( a , b , limit ) {
97
- // Ensure that `b` is the shorter string, minimizing memory use.
98
- if ( a . length < b . length ) {
99
- const aTmp = a ;
100
- a = b ;
101
- b = aTmp ;
102
- }
103
-
104
- const minDist = a . length - b . length ;
105
- // If we know the limit will be exceeded, we can return early.
106
- if ( minDist > limit ) {
107
- return limit + 1 ;
108
- }
109
-
110
- // Strip common prefix.
111
- // We know that `b` is the shorter string, so we don't need to check
112
- // `a.length`.
113
- while ( b . length > 0 && b [ 0 ] === a [ 0 ] ) {
114
- a = a . substring ( 1 ) ;
115
- b = b . substring ( 1 ) ;
116
- }
117
- // Strip common suffix.
118
- while ( b . length > 0 && b [ b . length - 1 ] === a [ a . length - 1 ] ) {
119
- a = a . substring ( 0 , a . length - 1 ) ;
120
- b = b . substring ( 0 , b . length - 1 ) ;
121
- }
122
-
123
- // If either string is empty, the distance is the length of the other.
124
- // We know that `b` is the shorter string, so we don't need to check `a`.
125
- if ( b . length === 0 ) {
126
- return minDist ;
127
- }
128
-
129
- const aLength = a . length ;
130
- const bLength = b . length ;
131
-
132
- for ( let i = 0 ; i <= bLength ; ++ i ) {
133
- editDistanceCurrent [ i ] = 0 ;
134
- editDistancePrev [ i ] = i ;
135
- editDistancePrevPrev [ i ] = Number . MAX_VALUE ;
136
- }
137
-
138
- // row by row
139
- for ( let i = 1 ; i <= aLength ; ++ i ) {
140
- editDistanceCurrent [ 0 ] = i ;
141
- const aIdx = i - 1 ;
142
-
143
- // column by column
144
- for ( let j = 1 ; j <= bLength ; ++ j ) {
145
- const bIdx = j - 1 ;
146
-
147
- // There is no cost to substitute a character with itself.
148
- const substitutionCost = a [ aIdx ] === b [ bIdx ] ? 0 : 1 ;
149
-
150
- editDistanceCurrent [ j ] = Math . min (
151
- // deletion
152
- editDistancePrev [ j ] + 1 ,
153
- // insertion
154
- editDistanceCurrent [ j - 1 ] + 1 ,
155
- // substitution
156
- editDistancePrev [ j - 1 ] + substitutionCost
157
- ) ;
158
-
159
- if ( ( i > 1 ) && ( j > 1 ) && ( a [ aIdx ] === b [ bIdx - 1 ] ) && ( a [ aIdx - 1 ] === b [ bIdx ] ) ) {
160
- // transposition
161
- editDistanceCurrent [ j ] = Math . min (
162
- editDistanceCurrent [ j ] ,
163
- editDistancePrevPrev [ j - 2 ] + 1
93
+ const editDistanceState = {
94
+ current : [ ] ,
95
+ prev : [ ] ,
96
+ prevPrev : [ ] ,
97
+ calculate : function calculate ( a , b , limit ) {
98
+ // Ensure that `b` is the shorter string, minimizing memory use.
99
+ if ( a . length < b . length ) {
100
+ const aTmp = a ;
101
+ a = b ;
102
+ b = aTmp ;
103
+ }
104
+
105
+ const minDist = a . length - b . length ;
106
+ // If we know the limit will be exceeded, we can return early.
107
+ if ( minDist > limit ) {
108
+ return limit + 1 ;
109
+ }
110
+
111
+ // Strip common prefix.
112
+ // We know that `b` is the shorter string, so we don't need to check
113
+ // `a.length`.
114
+ while ( b . length > 0 && b [ 0 ] === a [ 0 ] ) {
115
+ a = a . substring ( 1 ) ;
116
+ b = b . substring ( 1 ) ;
117
+ }
118
+ // Strip common suffix.
119
+ while ( b . length > 0 && b [ b . length - 1 ] === a [ a . length - 1 ] ) {
120
+ a = a . substring ( 0 , a . length - 1 ) ;
121
+ b = b . substring ( 0 , b . length - 1 ) ;
122
+ }
123
+
124
+ // If either string is empty, the distance is the length of the other.
125
+ // We know that `b` is the shorter string, so we don't need to check `a`.
126
+ if ( b . length === 0 ) {
127
+ return minDist ;
128
+ }
129
+
130
+ const aLength = a . length ;
131
+ const bLength = b . length ;
132
+
133
+ for ( let i = 0 ; i <= bLength ; ++ i ) {
134
+ this . current [ i ] = 0 ;
135
+ this . prev [ i ] = i ;
136
+ this . prevPrev [ i ] = Number . MAX_VALUE ;
137
+ }
138
+
139
+ // row by row
140
+ for ( let i = 1 ; i <= aLength ; ++ i ) {
141
+ this . current [ 0 ] = i ;
142
+ const aIdx = i - 1 ;
143
+
144
+ // column by column
145
+ for ( let j = 1 ; j <= bLength ; ++ j ) {
146
+ const bIdx = j - 1 ;
147
+
148
+ // There is no cost to substitute a character with itself.
149
+ const substitutionCost = a [ aIdx ] === b [ bIdx ] ? 0 : 1 ;
150
+
151
+ this . current [ j ] = Math . min (
152
+ // deletion
153
+ this . prev [ j ] + 1 ,
154
+ // insertion
155
+ this . current [ j - 1 ] + 1 ,
156
+ // substitution
157
+ this . prev [ j - 1 ] + substitutionCost
164
158
) ;
159
+
160
+ if ( ( i > 1 ) && ( j > 1 ) && ( a [ aIdx ] === b [ bIdx - 1 ] ) && ( a [ aIdx - 1 ] === b [ bIdx ] ) ) {
161
+ // transposition
162
+ this . current [ j ] = Math . min (
163
+ this . current [ j ] ,
164
+ this . prevPrev [ j - 2 ] + 1
165
+ ) ;
166
+ }
165
167
}
168
+
169
+ // Rotate the buffers, reusing the memory
170
+ const prevPrevTmp = this . prevPrev ;
171
+ this . prevPrev = this . prev ;
172
+ this . prev = this . current ;
173
+ this . current = prevPrevTmp ;
166
174
}
167
175
168
- // Rotate the buffers, reusing the memory
169
- const prevPrevTmp = editDistancePrevPrev ;
170
- editDistancePrevPrev = editDistancePrev ;
171
- editDistancePrev = editDistanceCurrent ;
172
- editDistanceCurrent = prevPrevTmp ;
173
- }
176
+ // `prev` because we already rotated the buffers.
177
+ const distance = this . prev [ bLength ] ;
178
+ return distance <= limit ? distance : ( limit + 1 ) ;
179
+ } ,
180
+ } ;
174
181
175
- // `prev` because we already rotated the buffers.
176
- const distance = editDistancePrev [ bLength ] ;
177
- return distance <= limit ? distance : ( limit + 1 ) ;
182
+ function editDistance ( a , b , limit ) {
183
+ return editDistanceState . calculate ( a , b , limit ) ;
178
184
}
179
185
180
186
function initSearch ( rawSearchIndex ) {
0 commit comments