【问题标题】:Levenshtein compare strings without changing numbersLevenshtein 比较字符串而不更改数字
【发布时间】:2016-08-22 07:29:08
【问题描述】:

我正在寻找一种方法来查找相似的符号名称,其中这些名称通常是文本和数字的组合,例如“value1”、“_value2”、“test_5”等。

现在为了找到相似的名称,我尝试使用 Levenshtein 距离,但对于算法,“_value1”和“.value1”之间的差异与“_value1”和“_value8”的差异相同。 有没有办法在不允许更改数字的情况下比较字符串?

我目前使用的代码来自http://www.dotnetperls.com/levenshtein

提前致谢!

【问题讨论】:

    标签: c# levenshtein-distance


    【解决方案1】:

    您可以为任何涉及数字的不等比较提供非常高的距离,例如 200。这将保持“_text1”和“.text1”之间的距离为 1(相似),但距离为 200(非常不同)在“text1”和“text10”之间。

    你可以通过改变第二步来做到这一点......

    // Step 2
    d[0, 0] = 0;
    
    for (int i = 1; i <= n; i++);
    {
        if('0' <= s[i - 1] && s[i - 1] <= '9')
            d[i, 0] = d[i-1, 0] + 200;
        else
            d[i, 0] = d[i-1, 0] + 1;
    }
    
    
    for (int j = 1; j <= m; j++)
    {
        if('0' <= t[j - 1] && t[j - 1] <= '9')
            d[0, j] = d[0, j-1] + 200;
        else
            d[0, j] = d[0, j-1] + 1;
    }
    

    ...和五个...

    // Step 5
    int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
    if(('0' <= t[j - 1] && t[j - 1] <= '9') ||
        '0' <= s[i - 1] && s[i - 1] <= '9'))
            cost *= 200;
    

    【讨论】:

    • 您好 Kottsil,感谢您的快速回复!这几乎就是我一直在寻找的解决方案,除了由于最后一个“Math.Min(...)”之间的最终区别,例如“var_3” 和 “var_1” 是 2,这仍然很低……但我可能自己能解决这个问题。顺便说一句:您的第一个“for(int i...)”需要以“i = 1”开头
    【解决方案2】:

    关于 Kittsil 的回答,这是我的完整解决方案。 我不确定它是否完全正确,但它似乎对我有用。

            ushort n = (ushort)s.Length;
            ushort m = (ushort)t.Length;
            ushort[,] d = new ushort[n + 1, m + 1];
    
            // Step 1
            if (n == 0)
            {
                return m;
            }
    
            if (m == 0)
            {
                return n;
            }
    
            // Step 2
            d[0, 0] = 0;
            for (int i = 1; i <= n; i++)
            {
                if ('0' <= s[i - 1] && s[i - 1] <= '9')
                    d[i, 0] = (ushort)(d[i - 1, 0] + 200);
                else
                    d[i, 0] = (ushort)(d[i - 1, 0] + 1);
            }
    
    
            for (int j = 1; j <= m; j++)
            {
                if ('0' <= t[j - 1] && t[j - 1] <= '9')
                    d[0, j] = (ushort)(d[0, j - 1] + 200);
                else
                    d[0, j] = (ushort)(d[0, j - 1] + 1);
            }
    
            // Step 3
            for (int i = 1; i <= n; i++)
            {
                //Step 4
                for (int j = 1; j <= m; j++)
                {
                    // Step 5
                    bool isIdentical = t[j - 1] == s[i - 1];
                    bool isNumber = ('0' <= t[j - 1] && t[j - 1] <= '9') || ('0' <= s[i - 1] && s[i - 1] <= '9');
    
                    int cost1 = isIdentical ? 0 : (isNumber ? 200 : 1);
                    int cost2 = isNumber ? 200 : 1;
    
                    // Step 6
                    d[i, j] = (ushort)(Math.Min(Math.Min(d[i - 1, j] + cost2, d[i, j - 1] + cost2), d[i - 1, j - 1] + cost1));
                }
            }
            // Step 7
            return d[n, m];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-25
      • 2013-05-06
      • 2013-11-12
      • 2020-07-07
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多