UNPKG

@linkdotnet/stringoperations

Version:

Collection of string utilities. Edit-Distances, Search and Data structures. Offers for example trie, levenshtein distance.

75 lines (74 loc) 3.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getLongestCommonSubsequence = exports.getClosestWords = exports.getClosestWord = void 0; function getClosestWord(base, ignoreCase, words) { const closestWords = getClosestWords(base, 1, ignoreCase, words); if (closestWords.length === 0) { return undefined; } return closestWords[0]; } exports.getClosestWord = getClosestWord; function getClosestWords(base, count, ignoreCase, words) { if (base.length === 0) { return []; } if (!words || words.length === 0) { return []; } const wordToSimiliarity = {}; for (let i = 0; i < words.length; i++) { wordToSimiliarity[words[i]] = getLongestCommonSubsequence(base, words[i], ignoreCase).length; } const sorted = Object.entries(wordToSimiliarity).sort((a, b) => { return b[1] - a[1]; }); return sorted.map(v => v[0]).slice(0, count); } exports.getClosestWords = getClosestWords; /** * Computes and returns the longest common subsequence of two strings * @param one First string * @param two Second string * @param ignoreCase If true, the string compares ignoring the case. So 'd' and 'D' would match * @returns Longest common subsequence * @remarks If ignoreCase is true, the casing of one will be returned as longest common subsequence. * If word one is 'HeLlO' and word two is 'Hallo' then 'HLlO' will be returned */ function getLongestCommonSubsequence(one, two, ignoreCase = false) { const lcsMatrix = createLongestCommonSubsequenceMatrix(one, two, ignoreCase); return getLongestCommonSubsequenceBackTrack(lcsMatrix, one, two, one.length, two.length, ignoreCase); } exports.getLongestCommonSubsequence = getLongestCommonSubsequence; function createLongestCommonSubsequenceMatrix(one, two, ignoreCase) { const lcsMatrix = new Array(one.length + 1).fill(0).map(() => new Array(two.length + 1).fill(0)); for (let i = 1; i <= one.length; i++) { for (let j = 1; j <= two.length; j++) { const characterEqual = ignoreCase ? one[i - 1].toUpperCase() === two[j - 1].toUpperCase() : one[i - 1] === two[j - 1]; if (characterEqual) { lcsMatrix[i][j] = lcsMatrix[i - 1][j - 1] + 1; } else { lcsMatrix[i][j] = Math.max(lcsMatrix[i - 1][j], lcsMatrix[i][j - 1]); } } } return lcsMatrix; } function getLongestCommonSubsequenceBackTrack(lcsMatrix, one, two, oneLength, twoLength, ignoreCase) { if (oneLength === 0 || twoLength === 0) { return ''; } const characterEqual = ignoreCase ? one[oneLength - 1].toUpperCase() === two[twoLength - 1].toUpperCase() : one[oneLength - 1] === two[twoLength - 1]; if (characterEqual) { return getLongestCommonSubsequenceBackTrack(lcsMatrix, one, two, oneLength - 1, twoLength - 1, ignoreCase) + one[oneLength - 1]; } if (lcsMatrix[oneLength][twoLength - 1] > lcsMatrix[oneLength - 1][twoLength]) { return getLongestCommonSubsequenceBackTrack(lcsMatrix, one, two, oneLength, twoLength - 1, ignoreCase); } return getLongestCommonSubsequenceBackTrack(lcsMatrix, one, two, oneLength - 1, twoLength, ignoreCase); }