UNPKG

fuzzy-rater

Version:

Tooling for fuzzily rating text according to some query

144 lines 16.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const FuzzyMultiWordMatcher_1 = require("../FuzzyMultiWordMatcher"); /** * Retrieves the distances for all matches for each of the inputs under the given matcher * @param matcher The matcher to use * @param inputs The inputs to match * @returns The distances for all matches */ function getDistances(matcher, inputs) { return inputs.map(text => { const match = matcher.getMatch(text); return match.map(d => d.distance); }); } /** * Maps a constant value over an input array * @param list The list of inputs to map the constants over * @param value The value to map to * @returns The list of values */ function map(list, value) { return list.map(() => value); } /** * Converts a string of alteration codes into the proper alteration types array * @param alterations The alterations string * @returns The alterations array */ function createAlterations(alterations) { const t = { i: "ignore", m: "match", r: "replace", a: "insert", s: "skip", }; return Array.from(alterations).map(s => { var _a; return (_a = t[s]) !== null && _a !== void 0 ? _a : ""; }); } describe("FuzzyMultiWordMatcher", () => { describe("new FuzzyMultiWordMatcher", () => { it("Doesn't error", () => { new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("oranges", 2); }); }); describe("FuzzyMultiWordMatcher.getMatch", () => { it("Should find whether text contains exact matches", () => { const matcher = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("oranges", 2); const match = matcher.getMatch("I like oranges and all oranges"); const noMatch = matcher.getMatch("Potatoes are amazing"); expect(match).toEqual([ { distance: 0, endIndex: 14 }, { endIndex: 30, distance: 0 }, ]); expect(noMatch).toEqual([]); }); it("Should find matches at most n characters away", () => { const matcher0 = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("oranges", 0); const matcher1 = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("oranges", 1); const matcher2 = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("oranges", 2); const matcher3 = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("oranges", 3); const matches = ["I like oranges", "oranges are nice"]; const with1mistake = [ "I like orange", "I like ornges", "orangles are nice", "oronges are cool", ]; const with2mistakes = [ "I like ornge", "I like orngaes", "orlangles are nice", "orongkes are cool", ]; const with3mistakes = [ "I like orne", "I like orngaees", "orflangles are nice", "orlongkes are cool", ]; const noMatches = [ "I like potaters", "hockey is cool sport", "That will be 4 bux baby", ]; expect(getDistances(matcher0, matches)).toEqual(map(matches, [0])); expect(getDistances(matcher0, with1mistake)).toEqual(map(with1mistake, [])); expect(getDistances(matcher0, with2mistakes)).toEqual(map(with2mistakes, [])); expect(getDistances(matcher0, with3mistakes)).toEqual(map(with3mistakes, [])); expect(getDistances(matcher0, noMatches)).toEqual(map(noMatches, [])); expect(getDistances(matcher1, matches)).toEqual(map(matches, [0])); expect(getDistances(matcher1, with1mistake)).toEqual(map(with1mistake, [1])); expect(getDistances(matcher1, with2mistakes)).toEqual(map(with2mistakes, [])); expect(getDistances(matcher1, with3mistakes)).toEqual(map(with3mistakes, [])); expect(getDistances(matcher1, noMatches)).toEqual(map(noMatches, [])); expect(getDistances(matcher2, matches)).toEqual(map(matches, [0])); expect(getDistances(matcher2, with1mistake)).toEqual(map(with1mistake, [1])); expect(getDistances(matcher2, with2mistakes)).toEqual(map(with2mistakes, [2])); expect(getDistances(matcher2, with3mistakes)).toEqual(map(with3mistakes, [])); expect(getDistances(matcher2, noMatches)).toEqual(map(noMatches, [])); expect(getDistances(matcher3, matches)).toEqual(map(matches, [0])); expect(getDistances(matcher3, with1mistake)).toEqual(map(with1mistake, [1])); expect(getDistances(matcher3, with2mistakes)).toEqual(map(with2mistakes, [2])); expect(getDistances(matcher3, with3mistakes)).toEqual(map(with3mistakes, [3])); expect(getDistances(matcher3, noMatches)).toEqual(map(noMatches, [])); }); it("Should find all the matches", () => { const matcher = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("oranges", 2); const match = matcher.getMatch("I like orangs with oranges and some orans"); expect(match).toEqual([ { endIndex: 13, distance: 1 }, { endIndex: 26, distance: 0 }, { endIndex: 41, distance: 2 }, ]); }); it("Should obtain the right distances", () => { const matcher = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("stragled", 2); const match = matcher.getMatch("where they sprawled amongst the tough stalks"); const match2 = matcher.getMatch("wedding guests straggled in pairs and groups"); expect(match.map(({ distance }) => distance)).toEqual([2]); expect(match2.map(({ distance }) => distance)).toEqual([1]); }); }); describe("FuzzyMultiWordMatcher.getMatchData", () => { it("Should retrieve the change data", () => { const matcher = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("potatlers", 2); const match = matcher.getMatchData("I like potatoes in germany are freaking potaltles you know?"); expect(match.alterations.map(({ type }) => type)).toEqual(createAlterations("iiiiiiimmmmmrmsmiiiiiiiiiiiiiiiiiiiiiiiiimmmmammmsmiiiiiiiiii")); expect(match.distances).toEqual([2, 2]); const match2 = matcher.getMatchData("I like potatoes with poetatlers and potatlers"); expect(match2.alterations.map(({ type }) => type)).toEqual(createAlterations("iiiiiiimmmmmrmsmiiiiiimmammmmmmmiiiiimmmmmmmmm")); expect(match2.distances).toEqual([2, 1, 0]); const matcher2 = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("oranne", 2); const match3 = matcher2.getMatchData("manner"); expect(match3.alterations.map(({ type }) => type)).toEqual(createAlterations("srmmmmi")); }); it("Shouldn't match unfinished words", () => { const matcher = new FuzzyMultiWordMatcher_1.FuzzyMultiWordMatcher("something", 2); const match = matcher.getMatchData("I like to do so"); expect(match.alterations.map(({ type }) => type)).toEqual(createAlterations("iiiiiiiiiiiiiii")); }); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRnV6enlNdWx0aVdvcmRNYXRjaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2Z1enp5UmF0ZS93b3JkTWF0Y2hlci9fdGVzdHMvRnV6enlNdWx0aVdvcmRNYXRjaGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsb0VBQStEO0FBRS9EOzs7OztHQUtHO0FBQ0gsU0FBUyxZQUFZLENBQUMsT0FBOEIsRUFBRSxNQUFnQjtJQUNsRSxPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDckIsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyQyxPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdEMsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLEdBQUcsQ0FBSSxJQUFXLEVBQUUsS0FBUTtJQUNqQyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDakMsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLFdBQW1CO0lBQzFDLE1BQU0sQ0FBQyxHQUFHO1FBQ04sQ0FBQyxFQUFFLFFBQVE7UUFDWCxDQUFDLEVBQUUsT0FBTztRQUNWLENBQUMsRUFBRSxTQUFTO1FBQ1osQ0FBQyxFQUFFLFFBQVE7UUFDWCxDQUFDLEVBQUUsTUFBTTtLQUNaLENBQUM7SUFDRixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLHdCQUFDLENBQUMsQ0FBQyxDQUFtQixDQUFDLG1DQUFJLEVBQUUsR0FBQSxDQUFDLENBQUM7QUFDMUUsQ0FBQztBQUVELFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSxH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QVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN0RSxNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25FLE1BQU0sQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDN0UsTUFBTSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzlFLE1BQU0sQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM5RSxNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdEUsTUFBTSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNuRSxNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxZQUFZLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdFLE1BQU0sQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxDQUFD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