C# 比较2个字符串

C# 比较2个字符串,c#,asp.net,.net,C#,Asp.net,.net,我有以下两个字符串: String A: Manchester United String B: Manchester Utd 两个字符串的含义相同,但包含不同的值 如何比较这些字符串以获得“匹配分数”,例如,在本例中,第一个单词是相似的,“Manchester”,第二个单词包含相似的字母,但不在正确的位置 有没有一个简单的算法在我提供2个字符串后返回“匹配分数”? ,你可以计算这两个字符串之间的关系,如果它小于某个值(你必须定义),你可以认为它们非常接近。p> 看看这篇文章,它解释了如何做,

我有以下两个字符串:

String A: Manchester United
String B: Manchester Utd
两个字符串的含义相同,但包含不同的值

如何比较这些字符串以获得“匹配分数”,例如,在本例中,第一个单词是相似的,“Manchester”,第二个单词包含相似的字母,但不在正确的位置


有没有一个简单的算法在我提供2个字符串后返回“匹配分数”?

,你可以计算这两个字符串之间的关系,如果它小于某个值(你必须定义),你可以认为它们非常接近。p> 看看这篇文章,它解释了如何做,并给出了示例代码:)

更新:

下面是将两个字符串作为参数并计算两个字符串的“Levenshtein距离”的方法代码

public static int Compute(string s, string t)
    {
    int n = s.Length;
    int m = t.Length;
    int[,] d = new int[n + 1, m + 1];

    // Step 1
    if (n == 0)
    {
        return m;
    }

    if (m == 0)
    {
        return n;
    }

    // Step 2
    for (int i = 0; i <= n; d[i, 0] = i++)
    {
    }

    for (int j = 0; j <= m; d[0, j] = j++)
    {
    }

    // Step 3
    for (int i = 1; i <= n; i++)
    {
        //Step 4
        for (int j = 1; j <= m; j++)
        {
        // Step 5
        int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;

        // Step 6
        d[i, j] = Math.Min(
            Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
            d[i - 1, j - 1] + cost);
        }
    }
    // Step 7
    return d[n, m];
    }
publicstaticint计算(字符串s,字符串t)
{
int n=s.长度;
int m=t.长度;
int[,]d=新的int[n+1,m+1];
//第一步
如果(n==0)
{
返回m;
}
如果(m==0)
{
返回n;
}
//步骤2

对于(int i=0;i,您要查找的是字符串相似性度量。有多种方法可以做到这一点:

  • 编辑两个字符串之间的距离(如答案#1)
  • 将字符串转换为字符集(通常在双字符或单词上),然后在两个字符集上计算Bruce系数或Dice系数
  • 将字符串投影到术语向量(在单词或双字符上)并计算两个向量之间的余弦距离
  • 我通常认为选项#2是最容易实现的,如果字符串是短语,那么您可以简单地在单词边界上标记它们。 在上述所有情况下,您可能希望在标记化之前首先删除停止词(常用词,如and、a、the等)。 更新:链接


    *警告:无耻的自我推销

    检测重复有时可能比计算Levenshtein数据“稍微”复杂。 考虑下面的例子:

    1. Jeff, Lynch, Maverick, Road, 181, Woodstock  
    2. Jeff, Alf., Lynch, Maverick, Rd, Woodstock, NY
    
    这种重复可以通过复杂的聚类算法进行匹配

    要了解更多信息,您可能需要查看一些研究论文,如 “用于大型数据库中重复检测的有效增量群集”


    (例子来自论文)

    我需要做类似的事情,并使用了Levenshtein距离

    我将其用于SQL Server UDF,该UDF用于具有超过一百万行(以及最多6或7个单词的文本)的查询

    我发现,如果分别比较每个单词,算法运行得更快,“相似性指数”更精确。即,将每个输入字符串拆分为单词,并将一个输入字符串的每个单词与另一个输入字符串的每个单词进行比较

    请记住,Levenshtein给出了差异,您必须将其转换为“相似性指数”。我使用了距离除以最长单词的长度(但有一些变化)

    第一条规则:单词的顺序和数量 您还必须考虑:

    • 如果两个输入中必须有相同的字数,或者可以更改
    • 如果两个输入的顺序必须相同,或者可以更改
    根据这一点,算法会发生变化。例如,如果字数不同,应用第一条规则会非常快。第二条规则会减少比较的次数,特别是当比较的文本中有很多单词时。这将在后面的示例中解释

    第二条规则:加权每个被比较对的相似性 我还对长单词的权重高于短单词的权重,以获得全局相似性指数。我的算法在比较词对中取两个单词中最长的一个,并赋予长单词对的权重高于短单词对的权重,尽管与词对长度不成正比

    样品比较:相同顺序 对于使用不同字数的示例:

    • 将“曼联”与“曼联曼联足球俱乐部”进行比较
    如果保证两个输入中的单词顺序相同,则应比较这些对:

    Manchester United
    Manchester Utd    FC
    
    (曼彻斯特,曼彻斯特)(曼联,曼联)(足球俱乐部:不可比较)

    (曼彻斯特,曼彻斯特)(曼联:不可比较)(曼联,足球俱乐部)

    曼彻斯特,曼联,曼联

    显然,第一组配对的得分最高

    实施 按相同的顺序比较单词

    字数较大的字符串是一个固定向量,在本例中显示为a、B、C、D、E。其中v[0]是单词a,v[1]是单词B,依此类推

    对于字数较少的字符串,我们需要创建所有可能的索引组合,以便与第一组进行比较。在这种情况下,字数较少的字符串由a、b、c表示

    您可以使用一个简单的循环来创建表示要比较的对的所有向量,如下所示

    A,B,C,D,E   A,B,C,D,E   A,B,C,D,E   A,B,C,D,E   A,B,C,D,E   A,B,C,D,E
    a,b,c       a,b,  c     a,b,    c   a,  b,c     a,  b,  c   a,    b,c
    0 1 2       0 1   3     0 1     4   0   2 3     0   2   4   0     3 4
    
    A,B,C,D,E   A,B,C,D,E   A,B,C,D,E   A,B,C,D,E
      a,b,c       a,b,  c     a,  b,c       a,b,c
      1 2 3       1 2   4     1   3 4       2 3 4
    
    样本中的数字是具有第一组单词索引的向量,这些索引必须与第一组单词中的索引一致。即v[0]=0,表示将短集(a)的索引0与长集(a)的索引0进行比较,v[1]=2表示将短集(b)的索引1与长集(C)的索引2进行比较,依此类推

    要计算此向量,只需从0,1,2开始。向右移动可移动的最新索引,直到无法再移动:

    通过移动最后一个来开始:

    0,1,2 -> 0,1,3 -> 0,1,4 
    No more moves possible, move the previous index, and restore the others
    to the lowest possible values (move 1 to 2, restore 4 to 3)
    
    当最后一个不能再移动时,移动最后一个之前的一个,并将最后一个重置到最近的可能位置(1移动到2,4移动到3):

    再次将一个移动到最后一个之前

    0,3,4
    No more moves possible of the last, move the one before the last
    Not possible, move the one before the one before the last, and reset the others:
    
    移动上一个:

    1,2,3 -> 1,2,4
    
    依此类推。看图片

    当您拥有所有可能的组合时,您可以比较定义的对

    第三条规则:停止比较的最小相似性 达到最小相似性时停止比较:取决于
    0,2,3 -> 0,2,4
    No more moves possible of the last, move the one before the last
    
    0,3,4
    No more moves possible of the last, move the one before the last
    Not possible, move the one before the one before the last, and reset the others:
    
    1,2,3 -> 1,2,4
    
        public static double CompareStrings(string strA, string strB)
        {
            List<string> setA = new List<string>();
            List<string> setB = new List<string>();
    
            for (int i = 0; i < strA.Length - 1; ++i)
                setA.Add(strA.Substring(i, 2));
    
            for (int i = 0; i < strB.Length - 1; ++i)
                setB.Add(strB.Substring(i, 2));
    
            var intersection = setA.Intersect(setB, StringComparer.InvariantCultureIgnoreCase);
    
            return (2.0 * intersection.Count()) / (setA.Count + setB.Count);
        }
    
    CompareStrings("Manchester United", "Manchester Utd");