📅  最后修改于: 2023-12-03 15:31:44.555000             🧑  作者: Mango
在 JavaScript 中,查找相似字符串是一个常见的问题。通常,我们需要比较两个字符串的相似度,以找出它们之间的相似性。
常用的相似度计算方法包括:
编辑距离(Edit distance)是指两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。可以使用动态规划算法来求解。具体的实现方法可以参考以下代码:
function editDistance(s1, s2) {
const m = s1.length;
const n = s2.length;
if (m === 0) {
return n;
}
if (n === 0) {
return m;
}
const d = [];
for (let i = 0; i <= m; i++) {
d[i] = [];
d[i][0] = i;
}
for (let j = 0; j <= n; j++) {
d[0][j] = j;
}
for (let j = 1; j <= n; j++) {
for (let i = 1; i <= m; i++) {
if (s1.charAt(i - 1) === s2.charAt(j - 1)) {
d[i][j] = d[i - 1][j - 1];
} else {
d[i][j] = Math.min(d[i - 1][j], d[i][j - 1], d[i - 1][j - 1]) + 1;
}
}
}
return d[m][n];
}
const s1 = 'kitten';
const s2 = 'sitting';
console.log(editDistance(s1, s2)); // 3
余弦相似度(Cosine similarity)是用来计算两个向量之间的相似度。在字符串相似度的计算中,可以将字符串看做是一个向量,根据字符串中的词语出现的频率来计算相似度。具体的实现方法可以参考以下代码:
function cosineSimilarity(s1, s2) {
const wordFreq1 = {};
const wordFreq2 = {};
s1.toLowerCase().replace(/[^A-Za-z0-9]+/g, ' ').trim().split(' ').forEach((word) => {
if (word !== '') {
wordFreq1[word] = (wordFreq1[word] || 0) + 1;
}
});
s2.toLowerCase().replace(/[^A-Za-z0-9]+/g, ' ').trim().split(' ').forEach((word) => {
if (word !== '') {
wordFreq2[word] = (wordFreq2[word] || 0) + 1;
}
});
const vec1 = [];
const vec2 = [];
Object.keys(wordFreq1).forEach((word) => {
vec1.push(wordFreq1[word]);
vec2.push(wordFreq2[word] || 0);
});
Object.keys(wordFreq2).forEach((word) => {
if (!wordFreq1[word]) {
vec1.push(0);
vec2.push(wordFreq2[word]);
}
});
let dotProduct = 0;
let norm1 = 0;
let norm2 = 0;
for (let i = 0; i < vec1.length; i++) {
dotProduct += vec1[i] * vec2[i];
norm1 += vec1[i] ** 2;
norm2 += vec2[i] ** 2;
}
return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
}
const s1 = 'JavaScript is a programming language';
const s2 = 'Programming is fun with JavaScript';
console.log(cosineSimilarity(s1, s2)); // 0.5
Jaccard 相似系数(Jaccard similarity coefficient)是计算两个集合之间相似度的一种方法。在字符串相似度的计算中,可以将字符串看做是一个集合,根据两个集合的交集和并集来计算相似度。具体的实现方法可以参考以下代码:
function jaccardSimilarity(s1, s2) {
const words1 = new Set(s1.toLowerCase().replace(/[^A-Za-z0-9]+/g, ' ').split(' '));
const words2 = new Set(s2.toLowerCase().replace(/[^A-Za-z0-9]+/g, ' ').split(' '));
const intersection = new Set([...words1].filter((word) => words2.has(word)));
const union = new Set([...words1, ...words2]);
return intersection.size / union.size;
}
const s1 = 'JavaScript is a programming language';
const s2 = 'Programming is fun with JavaScript';
console.log(jaccardSimilarity(s1, s2)); // 0.4
Levenshtein 距离是指两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。它也可以使用动态规划算法来求解。具体的实现方法可以参考编辑距离的实现方法。
Dice 系数是一种计算两个集合相似度的方法。它是 Jaccard 相似系数的一种改进,可以避免因集合大小差异而导致的偏差。具体的实现方法可以参考以下代码:
function diceCoefficient(s1, s2) {
const words1 = new Set(s1.toLowerCase().replace(/[^A-Za-z0-9]+/g, ' ').split(' '));
const words2 = new Set(s2.toLowerCase().replace(/[^A-Za-z0-9]+/g, ' ').split(' '));
const intersection = new Set([...words1].filter((word) => words2.has(word)));
return (2 * intersection.size) / (words1.size + words2.size);
}
const s1 = 'JavaScript is a programming language';
const s2 = 'Programming is fun with JavaScript';
console.log(diceCoefficient(s1, s2)); // 0.5
通过以上的实现方法,我们可以比较两个字符串的相似度,并按照实际需求选择合适的相似度计算方法。当然,还有很多其他的方法可以用来计算字符串相似度,需要根据实际情况进行选择。