You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
5.2 KiB
124 lines
5.2 KiB
"use strict"; |
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
exports.Trie = exports.defaultTrieOptions = void 0; |
|
const gensequence_1 = require("gensequence"); |
|
const suggest_1 = require("./suggest"); |
|
const util_1 = require("./util"); |
|
const walker_1 = require("./walker"); |
|
const _defaultTrieOptions = { |
|
compoundCharacter: '+', |
|
stripCaseAndAccentsPrefix: '~', |
|
forbiddenWordPrefix: '!', |
|
}; |
|
exports.defaultTrieOptions = Object.freeze(_defaultTrieOptions); |
|
function mergeOptionalWithDefaults(options) { |
|
const { compoundCharacter = exports.defaultTrieOptions.compoundCharacter, stripCaseAndAccentsPrefix = exports.defaultTrieOptions.stripCaseAndAccentsPrefix, forbiddenWordPrefix = exports.defaultTrieOptions.forbiddenWordPrefix, } = options || {}; |
|
return { compoundCharacter, stripCaseAndAccentsPrefix, forbiddenWordPrefix }; |
|
} |
|
class Trie { |
|
constructor(root, count, options) { |
|
this.root = root; |
|
this.count = count; |
|
this._options = mergeOptionalWithDefaults(options); |
|
} |
|
/** |
|
* Number of words in the Trie |
|
*/ |
|
size() { |
|
var _a; |
|
this.count = (_a = this.count) !== null && _a !== void 0 ? _a : util_1.countWords(this.root); |
|
return this.count; |
|
} |
|
get options() { |
|
return this._options; |
|
} |
|
find(text, minCompoundLength = false) { |
|
const minLength = !minCompoundLength || minCompoundLength === true ? undefined : minCompoundLength; |
|
return minCompoundLength ? this.findCompound(text, minLength) : this.findExact(text); |
|
} |
|
findCompound(text, minCompoundLength = 3, minLength = 0) { |
|
let n = this.root; |
|
let p; |
|
let q; |
|
for (p = 0; n && n.c && p < text.length; p = q) { |
|
n = n.c.get(text[p]); |
|
q = p + 1; |
|
if (n && n.f && q < text.length && q >= minCompoundLength) { |
|
const r = this.findCompound(text.slice(q), minCompoundLength, minCompoundLength); |
|
if (r && r.f) { |
|
return r; |
|
} |
|
} |
|
} |
|
return p === text.length && p >= minLength ? n : undefined; |
|
} |
|
findExact(text) { |
|
let n = this.root; |
|
let p; |
|
for (p = 0; n && n.c && p < text.length; ++p) { |
|
n = n.c.get(text[p]); |
|
} |
|
return p === text.length ? n : undefined; |
|
} |
|
has(word, minCompoundLength) { |
|
const n = this.find(word, minCompoundLength); |
|
return !!n && util_1.isWordTerminationNode(n); |
|
} |
|
/** |
|
* Provides an ordered sequence of words with the prefix of text. |
|
*/ |
|
completeWord(text) { |
|
const n = this.find(text); |
|
return gensequence_1.genSequence(n && util_1.isWordTerminationNode(n) ? [text] : []).concat(n ? util_1.iteratorTrieWords(n).map((suffix) => text + suffix) : []); |
|
} |
|
/** |
|
* Suggest spellings for `text`. The results are sorted by edit distance with changes near the beginning of a word having a greater impact. |
|
* @param text - the text to search for |
|
* @param maxNumSuggestions - the maximum number of suggestions to return. |
|
* @param compoundMethod - Use to control splitting words. |
|
* @param numChanges - the maximum number of changes allowed to text. This is an approximate value, since some changes cost less than others. |
|
* the lower the value, the faster results are returned. Values less than 4 are best. |
|
*/ |
|
suggest(text, maxNumSuggestions, compoundMethod, numChanges) { |
|
return this.suggestWithCost(text, maxNumSuggestions, compoundMethod, numChanges).map((a) => a.word); |
|
} |
|
/** |
|
* Suggest spellings for `text`. The results are sorted by edit distance with changes near the beginning of a word having a greater impact. |
|
* The results include the word and adjusted edit cost. This is useful for merging results from multiple tries. |
|
*/ |
|
suggestWithCost(text, maxNumSuggestions, compoundMethod, numChanges) { |
|
return suggest_1.suggest(this.root, text, maxNumSuggestions, compoundMethod, numChanges); |
|
} |
|
/** |
|
* genSuggestions will generate suggestions and send them to `collector`. `collector` is responsible for returning the max acceptable cost. |
|
* Costs are measured in weighted changes. A cost of 100 is the same as 1 edit. Some edits are considered cheaper. |
|
* Returning a MaxCost < 0 will effectively cause the search for suggestions to stop. |
|
*/ |
|
genSuggestions(collector, compoundMethod) { |
|
collector.collect(suggest_1.genSuggestions(this.root, collector.word, compoundMethod)); |
|
} |
|
/** |
|
* Returns an iterator that can be used to get all words in the trie. For some dictionaries, this can result in millions of words. |
|
*/ |
|
words() { |
|
return util_1.iteratorTrieWords(this.root); |
|
} |
|
/** |
|
* Allows iteration over the entire tree. |
|
* On the returned Iterator, calling .next(goDeeper: boolean), allows for controlling the depth. |
|
*/ |
|
iterate() { |
|
return walker_1.walker(this.root); |
|
} |
|
insert(word) { |
|
util_1.insert(word, this.root); |
|
return this; |
|
} |
|
static create(words, options) { |
|
const root = util_1.createTriFromList(words); |
|
util_1.orderTrie(root); |
|
return new Trie(root, undefined, options); |
|
} |
|
} |
|
exports.Trie = Trie; |
|
//# sourceMappingURL=trie.js.map
|