···1313 * Useful when only the differences in content are important, but not the order of the content
1414 * */
1515 reorder?: boolean;
1616+ /**
1717+ * When `reorder` is used this determines how to split each string into the tokens that will be reordered.
1818+ *
1919+ * The value of this property is used in String.split() -- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split#separator
2020+ *
2121+ * @default " "
2222+ * */
2323+ delimiter?: string | RegExp;
1624}
1725export interface StringSamenessResult {
1826 strategies: {
···1717];
1818exports.defaultStrategies = defaultStrategies;
1919const stringSameness = (valA, valB, options) => {
2020- const { transforms = index_js_2.strDefaultTransforms, strategies = defaultStrategies, reorder = false, } = options || {};
2121- const cleanA = transforms.reduce((acc, curr) => curr(acc), valA);
2020+ const { transforms = index_js_2.strDefaultTransforms, strategies = defaultStrategies, reorder = false, delimiter = ' ' } = options || {};
2121+ let cleanA = transforms.reduce((acc, curr) => curr(acc), valA);
2222 let cleanB = transforms.reduce((acc, curr) => curr(acc), valB);
2323- const shortest = cleanA.length > cleanB.length ? cleanB : cleanA;
2423 if (reorder) {
2524 // we want to ignore order of tokens as much as possible (user does not care about differences in word order, just absolute differences in characters overall)
2626- // so we will reorder cleanB so its tokens match the order or tokens in cleanA as closely as possible
2525+ // so we will reorder the shorter of the two strings so its tokens match the order of tokens in the longer string as closely as possible
2726 // before we run strategies
2828- cleanB = (0, exports.reorderStr)(cleanA, cleanB);
2727+ const [orderedX, orderedY] = (0, exports.reorderStr)(cleanA, cleanB);
2828+ cleanA = orderedX;
2929+ cleanB = orderedY;
2930 }
3131+ const shortest = cleanA.length > cleanB.length ? cleanB : cleanA;
3032 const stratResults = [];
3133 for (const strat of strategies) {
3234 if (strat.isValid !== undefined && !strat.isValid(cleanA, cleanB)) {
···6062 };
6163};
6264exports.stringSameness = stringSameness;
6363-const reorderStr = (cleanA, cleanB, options) => {
6464- // to do the reordering we will use stringSameness with the provided strats to match against each token in cleanA and choose the closest token in cleanB
6565- // and add the end concat any remaining tokens from cleanB to the reordered string
6666- const aTokens = cleanA.split(' ');
6767- const bTokens = cleanB.split(' ');
6868- const orderedCandidateTokens = aTokens.reduce((acc, curr) => {
6565+const reorderStr = (strA, strB, options) => {
6666+ const { transforms = index_js_2.strDefaultTransforms, strategies = defaultStrategies, delimiter = ' ' } = options || {};
6767+ const cleanA = transforms.reduce((acc, curr) => curr(acc), strA);
6868+ const cleanB = transforms.reduce((acc, curr) => curr(acc), strB);
6969+ // split by "token"
7070+ const eTokens = cleanA.split(delimiter);
7171+ const cTokens = cleanB.split(delimiter);
7272+ let longerTokens, shorterTokens;
7373+ if (eTokens.length > cTokens.length) {
7474+ longerTokens = eTokens;
7575+ shorterTokens = cTokens;
7676+ }
7777+ else {
7878+ longerTokens = cTokens;
7979+ shorterTokens = eTokens;
8080+ }
8181+ // we will use longest string (token list) as the reducer and order the shorter list to match it
8282+ // so we don't have to deal with undefined positions in the shorter list
8383+ const orderedCandidateTokens = longerTokens.reduce((acc, curr) => {
8484+ // if we've run out of tokens in the shorter list just return
8585+ if (acc.remaining.length === 0) {
8686+ return acc;
8787+ }
8888+ // on each iteration of tokens in the long list
8989+ // we iterate through remaining tokens from the shorter list and find the token with the most sameness
6990 let highScore = 0;
7091 let highIndex = 0;
7192 let index = 0;
7293 for (const token of acc.remaining) {
7373- const result = stringSameness(curr, token, { ...options, reorder: false });
7474- if (result.highScore > highScore) {
7575- highScore = result.highScore;
9494+ const result = stringSameness(curr, token, { strategies });
9595+ if (result.highScoreWeighted > highScore) {
9696+ highScore = result.highScoreWeighted;
7697 highIndex = index;
7798 }
7899 index++;
79100 }
101101+ // then remove the most same token from the remaining short list tokens
80102 const splicedRemaining = [...acc.remaining];
8181- if (highIndex <= splicedRemaining.length - 1) {
8282- splicedRemaining.splice(highIndex, 1);
8383- }
8484- const ordered = highIndex <= acc.remaining.length - 1 ? acc.ordered.concat(acc.remaining[highIndex]) : acc.ordered;
8585- return { ordered: ordered, remaining: splicedRemaining };
8686- }, { ordered: [], remaining: bTokens });
8787- const allOrderedCandidateTokens = orderedCandidateTokens.ordered.concat(orderedCandidateTokens.remaining);
8888- return allOrderedCandidateTokens.join(' ');
103103+ splicedRemaining.splice(highIndex, 1);
104104+ return {
105105+ // finally add the most same token to the ordered short list
106106+ ordered: acc.ordered.concat(acc.remaining[highIndex]),
107107+ // and return the remaining short list tokens
108108+ remaining: splicedRemaining
109109+ };
110110+ }, {
111111+ // "ordered" is the result of ordering tokens in the shorter list to match longer token order
112112+ ordered: [],
113113+ // remaining is the initial shorter list
114114+ remaining: shorterTokens
115115+ });
116116+ return [longerTokens.join(' '), orderedCandidateTokens.ordered.join(' ')];
89117};
90118exports.reorderStr = reorderStr;
91119const createStringSameness = (defaults) => {
···1313 * Useful when only the differences in content are important, but not the order of the content
1414 * */
1515 reorder?: boolean;
1616+ /**
1717+ * When `reorder` is used this determines how to split each string into the tokens that will be reordered.
1818+ *
1919+ * The value of this property is used in String.split() -- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split#separator
2020+ *
2121+ * @default " "
2222+ * */
2323+ delimiter?: string | RegExp;
1624}
1725export interface StringSamenessResult {
1826 strategies: {
···1111 cosineStrategy
1212];
1313const stringSameness = (valA, valB, options) => {
1414- const { transforms = strDefaultTransforms, strategies = defaultStrategies, reorder = false, } = options || {};
1515- const cleanA = transforms.reduce((acc, curr) => curr(acc), valA);
1414+ const { transforms = strDefaultTransforms, strategies = defaultStrategies, reorder = false, delimiter = ' ' } = options || {};
1515+ let cleanA = transforms.reduce((acc, curr) => curr(acc), valA);
1616 let cleanB = transforms.reduce((acc, curr) => curr(acc), valB);
1717- const shortest = cleanA.length > cleanB.length ? cleanB : cleanA;
1817 if (reorder) {
1918 // we want to ignore order of tokens as much as possible (user does not care about differences in word order, just absolute differences in characters overall)
2020- // so we will reorder cleanB so its tokens match the order or tokens in cleanA as closely as possible
1919+ // so we will reorder the shorter of the two strings so its tokens match the order of tokens in the longer string as closely as possible
2120 // before we run strategies
2222- cleanB = reorderStr(cleanA, cleanB);
2121+ const [orderedX, orderedY] = reorderStr(cleanA, cleanB);
2222+ cleanA = orderedX;
2323+ cleanB = orderedY;
2324 }
2525+ const shortest = cleanA.length > cleanB.length ? cleanB : cleanA;
2426 const stratResults = [];
2527 for (const strat of strategies) {
2628 if (strat.isValid !== undefined && !strat.isValid(cleanA, cleanB)) {
···5355 highScoreWeighted,
5456 };
5557};
5656-export const reorderStr = (cleanA, cleanB, options) => {
5757- // to do the reordering we will use stringSameness with the provided strats to match against each token in cleanA and choose the closest token in cleanB
5858- // and add the end concat any remaining tokens from cleanB to the reordered string
5959- const aTokens = cleanA.split(' ');
6060- const bTokens = cleanB.split(' ');
6161- const orderedCandidateTokens = aTokens.reduce((acc, curr) => {
5858+export const reorderStr = (strA, strB, options) => {
5959+ const { transforms = strDefaultTransforms, strategies = defaultStrategies, delimiter = ' ' } = options || {};
6060+ const cleanA = transforms.reduce((acc, curr) => curr(acc), strA);
6161+ const cleanB = transforms.reduce((acc, curr) => curr(acc), strB);
6262+ // split by "token"
6363+ const eTokens = cleanA.split(delimiter);
6464+ const cTokens = cleanB.split(delimiter);
6565+ let longerTokens, shorterTokens;
6666+ if (eTokens.length > cTokens.length) {
6767+ longerTokens = eTokens;
6868+ shorterTokens = cTokens;
6969+ }
7070+ else {
7171+ longerTokens = cTokens;
7272+ shorterTokens = eTokens;
7373+ }
7474+ // we will use longest string (token list) as the reducer and order the shorter list to match it
7575+ // so we don't have to deal with undefined positions in the shorter list
7676+ const orderedCandidateTokens = longerTokens.reduce((acc, curr) => {
7777+ // if we've run out of tokens in the shorter list just return
7878+ if (acc.remaining.length === 0) {
7979+ return acc;
8080+ }
8181+ // on each iteration of tokens in the long list
8282+ // we iterate through remaining tokens from the shorter list and find the token with the most sameness
6283 let highScore = 0;
6384 let highIndex = 0;
6485 let index = 0;
6586 for (const token of acc.remaining) {
6666- const result = stringSameness(curr, token, { ...options, reorder: false });
6767- if (result.highScore > highScore) {
6868- highScore = result.highScore;
8787+ const result = stringSameness(curr, token, { strategies });
8888+ if (result.highScoreWeighted > highScore) {
8989+ highScore = result.highScoreWeighted;
6990 highIndex = index;
7091 }
7192 index++;
7293 }
9494+ // then remove the most same token from the remaining short list tokens
7395 const splicedRemaining = [...acc.remaining];
7474- if (highIndex <= splicedRemaining.length - 1) {
7575- splicedRemaining.splice(highIndex, 1);
7676- }
7777- const ordered = highIndex <= acc.remaining.length - 1 ? acc.ordered.concat(acc.remaining[highIndex]) : acc.ordered;
7878- return { ordered: ordered, remaining: splicedRemaining };
7979- }, { ordered: [], remaining: bTokens });
8080- const allOrderedCandidateTokens = orderedCandidateTokens.ordered.concat(orderedCandidateTokens.remaining);
8181- return allOrderedCandidateTokens.join(' ');
9696+ splicedRemaining.splice(highIndex, 1);
9797+ return {
9898+ // finally add the most same token to the ordered short list
9999+ ordered: acc.ordered.concat(acc.remaining[highIndex]),
100100+ // and return the remaining short list tokens
101101+ remaining: splicedRemaining
102102+ };
103103+ }, {
104104+ // "ordered" is the result of ordering tokens in the shorter list to match longer token order
105105+ ordered: [],
106106+ // remaining is the initial shorter list
107107+ remaining: shorterTokens
108108+ });
109109+ return [longerTokens.join(' '), orderedCandidateTokens.ordered.join(' ')];
82110};
83111const createStringSameness = (defaults) => {
84112 return (valA, valB, options = {}) => stringSameness(valA, valB, { ...defaults, ...options });