fuzzy-rater
Version:
Tooling for fuzzily rating text according to some query
98 lines • 7.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FuzzyWordMatcher = void 0;
const createFuzzyNFATemplate_1 = require("./createFuzzyNFATemplate");
const NFADFA_1 = require("../../DFA/NFADFA/NFADFA");
const merge_1 = require("../../utils/merge");
/**
* A fuzzy word matcher that can be used to find a word in a number of items.
* Initial setup time is relatively long, but matching per string happens in linear time.
*/
class FuzzyWordMatcher {
/**
* Constructs a new fuzzy word matcher
* @param word The word to look for
* @param maxDistance The maximum error
*/
constructor(word, maxDistance) {
this.word = word;
this.maxDistance = maxDistance;
this.initialize(word, maxDistance);
}
/**
* Initializes the data structures used for rating
* @param word The word to look for
* @param maxDistance The maximal allowed distance
*/
initialize(word, maxDistance) {
const nfaTemplate = createFuzzyNFATemplate_1.createFuzzyNFATemplate(word, maxDistance);
this.NFA = new NFADFA_1.NFADFA(nfaTemplate);
}
/**
* Finds the best match in a set of NFA nodes
* @param matches The nodes to find the best match in
* @param getNode Retrieves the node data
* @returns The best match
*/
getBestMatch(matches, getNode) {
const best = matches.reduce((best, m) => {
const node = getNode(m);
return node.matched && (best == null || node.distance < best.distance)
? { item: m, distance: node.distance }
: best;
}, undefined);
return best === null || best === void 0 ? void 0 : best.item;
}
/**
* Retrieves the best match in the given text
* @param text The text to find the query word in
* @returns Whether the text matched, and the distance from the query word
*/
getMatch(text) {
// Execute the DFA
const matches = this.NFA.execute(text);
// Find the best match
const best = this.getBestMatch(matches, node => node);
// Return the result
if (best)
return { matched: true, distance: best.distance };
return { matched: false, distance: Infinity };
}
/**
* Retrieves the best match in the given text, and data of how to obtain it
* @param text The text to find the query word in
* @returns Whether the text matched, and the distance from the query word, and how the text differed
*/
getMatchData(text) {
var _a;
const matches = this.NFA.executeTraced(text);
const best = this.getBestMatch(matches, ({ final }) => final);
const trace = best === null || best === void 0 ? void 0 : best.getPath();
// Convert the NFA trace to an alterations array
if (best && trace) {
const alterations = (_a = trace.reduce(({ alterations, index }, { transition }) => {
var _a;
const target = {
index,
character: transition.type == "skip" ? "" : text[index],
};
const query = {
index: transition.index,
character: (_a = transition.character) !== null && _a !== void 0 ? _a : "",
};
return {
alterations: merge_1.add(alterations, {
target,
query,
type: transition.type,
}),
index: transition.type == "skip" ? index : index + 1,
};
}, { alterations: [], index: 0 })) === null || _a === void 0 ? void 0 : _a.alterations;
return { matched: true, distance: best.final.distance, alterations };
}
return { matched: false, distance: Infinity, alterations: [] };
}
}
exports.FuzzyWordMatcher = FuzzyWordMatcher;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRnV6enlXb3JkTWF0Y2hlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mdXp6eVJhdGUvd29yZE1hdGNoZXIvRnV6enlXb3JkTWF0Y2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFBZ0U7QUFJaEUsb0RBQStDO0FBQy9DLDZDQUFzQztBQUV0Qzs7O0dBR0c7QUFDSCxNQUFhLGdCQUFnQjtJQUt6Qjs7OztPQUlHO0lBQ0gsWUFBbUIsSUFBWSxFQUFFLFdBQW1CO1FBQ2hELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7OztPQUlHO0lBQ08sVUFBVSxDQUFDLElBQVksRUFBRSxXQUFtQjtRQUNsRCxNQUFNLFdBQVcsR0FBRywrQ0FBc0IsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLGVBQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDTyxZQUFZLENBQ2xCLE9BQVksRUFDWixPQUFvQztRQUVwQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3BDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN4QixPQUFPLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztnQkFDbEUsQ0FBQyxDQUFDLEVBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBQztnQkFD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