在 C# 中计算字符串相似度有多种方法,包括使用编辑距离(例如 Levenshtein 距离)、Jaro-Winkler 相似度和 Cosine 相似度等。在这里,我们重点介绍一种常用的方法——Levenshtein 距离,并给出如何使用它来计算字符串相似度。
Levenshtein 距离是一种用于衡量两个字符串之间差异的度量。它表示将一个字符串转换为另一个字符串所需的最少单字符编辑操作(插入、删除或替换)的数量。
以下是 Levenshtein
距离计算及字符串相似度计算的完整代码,包括详细的注释和解释:
using System;
public static class StringSimilarity
{
/// <summary>
/// 计算两个字符串之间的 Levenshtein 距离。
/// Levenshtein 距离是将一个字符串转换为另一个字符串所需的最少单字符编辑操作(插入、删除或替换)的数量。
/// </summary>
/// <param name="source">源字符串</param>
/// <param name="target">目标字符串</param>
/// <returns>Levenshtein 距离</returns>
public static int ComputeLevenshteinDistance(string source, string target)
{
// 如果源字符串为空,则返回目标字符串的长度(即需要的操作数)
if (string.IsNullOrEmpty(source)) return target.Length;
// 如果目标字符串为空,则返回源字符串的长度(即需要的操作数)
if (string.IsNullOrEmpty(target)) return source.Length;
int sourceLength = source.Length;
int targetLength = target.Length;
// 创建一个 (sourceLength + 1) x (targetLength + 1) 的矩阵
var matrix = new int[sourceLength + 1, targetLength + 1];
// 初始化矩阵的第一行,表示从空字符串到目标字符串的转换成本(即插入操作数)
for (int i = 0; i <= sourceLength; i++)
matrix[i, 0] = i;
// 初始化矩阵的第一列,表示从源字符串到空字符串的转换成本(即删除操作数)
for (int j = 0; j <= targetLength; j++)
matrix[0, j] = j;
// 填充矩阵的其余部分
for (int i = 1; i <= sourceLength; i++)
{
for (int j = 1; j <= targetLength; j++)
{
// 如果当前字符相同,成本为 0;否则,成本为 1
int cost = (target[j - 1] == source[i - 1]) ? 0 : 1;
// 计算当前位置的值,取左边 + 1、上面 + 1、左上角 + cost 中的最小值
matrix[i, j] = Math.Min(
Math.Min(matrix[i - 1, j] + 1, matrix[i, j - 1] + 1), // 删除或插入操作
matrix[i - 1, j - 1] + cost); // 替换操作
}
}
// 返回右下角的值,即两个字符串的 Levenshtein 距离
return matrix[sourceLength, targetLength];
}
/// <summary>
/// 计算两个字符串的相似度。
/// 相似度是根据 Levenshtein 距离计算的,取值范围为 0 到 1,其中 1 表示完全匹配。
/// </summary>
/// <param name="source">源字符串</param>
/// <param name="target">目标字符串</param>
/// <returns>字符串相似度,范围从 0 到 1</returns>
public static double ComputeSimilarity(string source, string target)
{
// 如果源字符串或目标字符串为空,返回 0 相似度
if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(target)) return 0.0;
// 计算 Levenshtein 距离
int levDistance = ComputeLevenshteinDistance(source, target);
// 计算两个字符串的最大长度
int maxLength = Math.Max(source.Length, target.Length);
// 计算相似度,公式为 1 - (Levenshtein 距离 / 最大长度)
// 如果 maxLength 为 0(即两个字符串都为空),相似度为 1
return maxLength == 0 ? 1.0 : 1.0 - (double)levDistance / maxLength;
}
}
class Program
{
static void Main(string[] args)
{
// 定义两个测试字符串
string str1 = "字符串1";
string str2 = "字符串122";
// 计算这两个字符串的相似度
double similarity = StringSimilarity.ComputeSimilarity(str1, str2);
// 输出相似度,使用百分比格式(例如 80%)
Console.WriteLine($"字符串 \"{str1}\" 和 \"{str2}\" 的相似度为: {similarity:P2}");
}
}
代码解释
-
ComputeLevenshteinDistance
方法:- 功能:计算两个字符串之间的 Levenshtein 距离。
- 参数:
source
(源字符串)、target
(目标字符串)。 - 返回:Levenshtein 距离。
- 步骤:
- 如果任一字符串为空,则直接返回另一个字符串的长度。
- 初始化矩阵的第一行和第一列,用于处理从空字符串到目标或源字符串的转换。
- 使用动态规划算法填充矩阵。
- 返回矩阵右下角的值,即最终的 Levenshtein 距离。
-
ComputeSimilarity
方法:- 功能:根据 Levenshtein 距离计算两个字符串的相似度。
- 参数:
source
(源字符串)、target
(目标字符串)。 - 返回:相似度,范围从 0 到 1。
- 步骤:
- 如果任一字符串为空,则返回 0 相似度。
- 计算 Levenshtein 距离。
- 根据距离和字符串的最大长度计算相似度。
- 如果最大长度为 0(两个字符串都为空),则相似度为 1。
-
Main
方法:- 功能:演示如何使用
StringSimilarity
类来计算两个字符串的相似度。 - 步骤:
- 定义两个测试字符串。
- 计算并输出它们的相似度,结果格式为百分比(例如 80%)。
- 功能:演示如何使用
总结
以上代码展示了如何使用 Levenshtein 距离来计算字符串之间的相似度,并将结果转化为一个方便理解的相似度百分比。这种方法可以用于各种文本处理任务,例如拼写检查、文本匹配和数据清洗等。