fuzzy-rater
Version:
Tooling for fuzzily rating text according to some query
94 lines • 7.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FuzzyWordMatcher = void 0;
const createFuzzyNFATemplate_1 = require("./createFuzzyNFATemplate");
const NFADFA_1 = require("../DFA/NFADFA/NFADFA");
/**
* 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 rater
* @param word The word to look for
* @param maxDistance The maximum error
*/
constructor(word, 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: [
...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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRnV6enlXb3JkTWF0Y2hlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9mdXp6eVJhdGUvRnV6enlXb3JkTWF0Y2hlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxxRUFBZ0U7QUFJaEUsaURBQTRDO0FBRTVDOzs7R0FHRztBQUNILE1BQWEsZ0JBQWdCO0lBR3pCOzs7O09BSUc7SUFDSCxZQUFtQixJQUFZLEVBQUUsV0FBbUI7UUFDaEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVEOzs7O09BSUc7SUFDTyxVQUFVLENBQUMsSUFBWSxFQUFFLFdBQW1CO1FBQ2xELE1BQU0sV0FBVyxHQUFHLCtDQUFzQixDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksZUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNPLFlBQVksQ0FDbEIsT0FBWSxFQUNaLE9BQW9DO1FBRXBDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDcEMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hCLE9BQU8sSUFBSSxDQUFDLE9BQU8sSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO2dCQUNsRSxDQUFDLENBQUMsRUFBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFDO2dCQUNwQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ2YsQ0FBQyxFQUFFLFNBQW9ELENBQUMsQ0FBQztRQUN6RCxPQUFPLElBQUksYUFBSixJQUFJLHVCQUFKLElBQUksQ0FBRSxJQUFJ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