natural 8.1.2 → 8.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -74,6 +74,7 @@ jobs:
74
74
 
75
75
  # Save coverage report in Coveralls
76
76
  - name: Coveralls
77
- uses: coverallsapp/github-action@master
77
+ if: matrix.node-version == '22.x'
78
+ uses: coverallsapp/github-action@v2
78
79
  with:
79
80
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -153,6 +153,7 @@ function levenshteinDistance (source, target, options) {
153
153
 
154
154
  let lastColMatch = null
155
155
  for (let row = 1; row <= sourceLength; row++) {
156
+ const sourceElement = source[row - 1]
156
157
  if (isUnrestrictedDamerau) {
157
158
  lastColMatch = null
158
159
  }
@@ -160,7 +161,6 @@ function levenshteinDistance (source, target, options) {
160
161
  const costToInsert = distanceMatrix[row][column - 1].cost + options.insertion_cost
161
162
  const costToDelete = distanceMatrix[row - 1][column].cost + options.deletion_cost
162
163
 
163
- const sourceElement = source[row - 1]
164
164
  const targetElement = target[column - 1]
165
165
  let costToSubstitute = distanceMatrix[row - 1][column - 1].cost
166
166
  if (sourceElement !== targetElement) {
@@ -218,13 +218,13 @@ function levenshteinDistance (source, target, options) {
218
218
 
219
219
  distanceMatrix[row][column] = { cost: minCostParent.cost, parentCell: minCostParent.coordinates }
220
220
 
221
- if (isUnrestrictedDamerau) {
222
- lastRowMap[sourceElement] = row
223
- if (sourceElement === targetElement) {
224
- lastColMatch = column
225
- }
221
+ if (isUnrestrictedDamerau && sourceElement === targetElement) {
222
+ lastColMatch = column
226
223
  }
227
224
  }
225
+ if (isUnrestrictedDamerau) {
226
+ lastRowMap[sourceElement] = row
227
+ }
228
228
  }
229
229
 
230
230
  if (!options.search) {
@@ -46,23 +46,21 @@ class Trie {
46
46
  string = string.toLowerCase()
47
47
  }
48
48
 
49
- // If the string has only one letter, mark this as a word.
50
- if (string.length === 0) {
51
- const wasWord = this.$
52
- this.$ = true
53
- return wasWord
54
- }
55
-
56
- // Make sure theres a Trie node in our dictionary
57
- let next = this.dictionary[string[0]]
49
+ const caseSensitive = this.cs
50
+ let node = this
58
51
 
59
- if (!next) {
60
- this.dictionary[string[0]] = new Trie(this.cs)
61
- next = this.dictionary[string[0]]
52
+ for (let index = 0, length = string.length; index < length; index++) {
53
+ const character = string[index]
54
+ let next = node.dictionary[character]
55
+ if (!next) {
56
+ node.dictionary[character] = next = new Trie(caseSensitive)
57
+ }
58
+ node = next
62
59
  }
63
60
 
64
- // Continue adding the string
65
- return next.addString(string.substring(1))
61
+ const wasWord = node.$
62
+ node.$ = true
63
+ return wasWord
66
64
  }
67
65
 
68
66
  /**
@@ -94,9 +92,11 @@ class Trie {
94
92
  }
95
93
 
96
94
  function get (node, word) {
97
- if (!node) return null
98
- if (word.length === 0) return node
99
- return get(node.dictionary[word[0]], word.substring(1))
95
+ for (let index = 0, length = word.length; index < length; index++) {
96
+ if (!node) return null
97
+ node = node.dictionary[word[index]]
98
+ }
99
+ return node || null
100
100
  }
101
101
 
102
102
  function recurse (node, stringAgg, resultsAgg) {
@@ -130,21 +130,15 @@ class Trie {
130
130
  string = string.toLowerCase()
131
131
  }
132
132
 
133
- if (string.length === 0) {
134
- return this.$
135
- }
136
-
137
- // Otherwise, we need to continue searching
138
- const firstLetter = string[0]
139
- const next = this.dictionary[firstLetter]
140
-
141
- // If we don't have a node, this isn't a word
142
- if (!next) {
143
- return false
133
+ let node = this
134
+ for (let index = 0, length = string.length; index < length; index++) {
135
+ node = node.dictionary[string[index]]
136
+ if (!node) {
137
+ return false
138
+ }
144
139
  }
145
140
 
146
- // Otherwise continue the search at the next node
147
- return next.contains(string.substring(1))
141
+ return node.$
148
142
  }
149
143
 
150
144
  /**
@@ -161,26 +155,27 @@ class Trie {
161
155
  search = search.toLowerCase()
162
156
  }
163
157
 
164
- function recurse (node, search, stringAgg, resultsAgg) {
158
+ const results = []
159
+ let node = this
160
+ const length = search.length
161
+
162
+ for (let index = 0; ; index++) {
165
163
  // Check if this is a word.
166
164
  if (node.$) {
167
- resultsAgg.push(stringAgg)
165
+ results.push(search.slice(0, index))
168
166
  }
169
167
 
170
168
  // Check if the have completed the seearch
171
- if (search.length === 0) {
172
- return resultsAgg
169
+ if (index === length) {
170
+ return results
173
171
  }
174
172
 
175
173
  // Otherwise, continue searching
176
- const next = node.dictionary[search[0]]
177
- if (!next) {
178
- return resultsAgg
174
+ node = node.dictionary[search[index]]
175
+ if (!node) {
176
+ return results
179
177
  }
180
- return recurse(next, search.substring(1), stringAgg + search[0], resultsAgg)
181
- };
182
-
183
- return recurse(this, search, '', [])
178
+ }
184
179
  }
185
180
 
186
181
  /**
@@ -192,26 +187,33 @@ class Trie {
192
187
  search = search.toLowerCase()
193
188
  }
194
189
 
195
- function recurse (node, search, stringAgg, lastWord) {
190
+ let node = this
191
+ let lastWordIndex = null
192
+ const length = search.length
193
+
194
+ for (let index = 0; ; index++) {
196
195
  // Check if this is a word
197
196
  if (node.$) {
198
- lastWord = stringAgg
197
+ lastWordIndex = index
199
198
  }
200
199
 
201
200
  // Check if we have no more to search
202
- if (search.length === 0) {
203
- return [lastWord, search]
201
+ if (index === length) {
202
+ return [
203
+ lastWordIndex === null ? null : search.slice(0, lastWordIndex),
204
+ ''
205
+ ]
204
206
  }
205
207
 
206
208
  // Continue searching
207
- const next = node.dictionary[search[0]]
208
- if (!next) {
209
- return [lastWord, search]
209
+ node = node.dictionary[search[index]]
210
+ if (!node) {
211
+ return [
212
+ lastWordIndex === null ? null : search.slice(0, lastWordIndex),
213
+ search.slice(index)
214
+ ]
210
215
  }
211
- return recurse(next, search.substring(1), stringAgg + search[0], lastWord)
212
- };
213
-
214
- return recurse(this, search, '', null)
216
+ }
215
217
  }
216
218
 
217
219
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "natural",
3
3
  "description": "General natural language (tokenizing, stemming (English, Russian, Spanish), part-of-speech tagging, sentiment analysis, classification, inflection, phonetics, tfidf, WordNet, jaro-winkler, Levenshtein distance, Dice's Coefficient) facilities for node.",
4
- "version": "8.1.2",
4
+ "version": "8.2.1",
5
5
  "homepage": "https://github.com/NaturalNode/natural",
6
6
  "repository": {
7
7
  "type": "git",