📜  javascript 查找相似字符串 - Javascript (1)

📅  最后修改于: 2023-12-03 15:31:44.555000             🧑  作者: Mango

JavaScript 查找相似字符串 - JavaScript

在 JavaScript 中,查找相似字符串是一个常见的问题。通常,我们需要比较两个字符串的相似度,以找出它们之间的相似性。

相似度计算方法

常用的相似度计算方法包括:

  • 编辑距离
  • 余弦相似度
  • Jaccard 相似系数
  • Levenshtein 距离
  • Dice 系数
编辑距离

编辑距离(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 相似系数(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 距离

Levenshtein 距离是指两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。它也可以使用动态规划算法来求解。具体的实现方法可以参考编辑距离的实现方法。

Dice 系数

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
总结

通过以上的实现方法,我们可以比较两个字符串的相似度,并按照实际需求选择合适的相似度计算方法。当然,还有很多其他的方法可以用来计算字符串相似度,需要根据实际情况进行选择。