【问题标题】:Comparing file paths using Levenshtein Distance使用 Levenshtein 距离比较文件路径
【发布时间】:2016-03-28 03:28:47
【问题描述】:

我需要弄清楚特定文件路径的接近程度,Levenshtein 距离算法效果很好,但我需要以某种方式为目录树上更高的目录赋予权重。

例如:

我的来源是“x:/t/c/d”

我的两个目标是:

  • “a:/t/c/d”
  • “x:/t/y/z”

我需要将第二个目标识别为更接近,即使“作为字符串”它的编辑距离更大(因为目标二与源位于同一父目录“x”中,而第一个目标正在查看目录“一个”。

我将如何对字符串中较早出现的字符进行加权?

【问题讨论】:

  • 为什么有人投了反对票?感觉这个问题很有意义,这个人查找了 Levenshtein 距离并应用了它,所以不确定反对票是为了什么

标签: java c# algorithm comparison string-comparison


【解决方案1】:

在我看来,完整路径上的 Levenshtein 距离 不是您想要实现的正确算法。

我建议您将路径拆分为一个文件夹列表(最终在末尾有一个文件),然后我会比较相应位置的目录名称(或驱动器),如果它给它一个高分是一个完美的匹配,随着你在目录树中的深入,分数会降低。

如果不匹配,您仍然可以在路径上应用 Levenshtein 距离并将其相乘以获得随着您进一步下降而减小的权重。

总结一下。

例如:

var source = "x:/t/c/d";
var targets = new[] { "a:/t/c/d", "x:/t/y/z" };

var separator = '/';
var sourceParts = source.Split(separator);
var weight = 10;
var match = 100;

var scores = targets.Select(target =>
{
    var score = sourceParts
        .Zip(target.Split(separator), (s, t) => new Tuple<string, string>(s, t))
        .Select(
            (tuple, i) => tuple.Item1 == tuple.Item2
                ? match * GetWeight(i)
                : LevenshteinDistance(tuple.Item1, tuple.Item2) * GetWeight(i)
        ).Sum();

    return new
    {
        Target = target,
        Score = score
    };
});

GetWeight() 类似于:

private static int MaxWeight = 10;
private static int GetWeight(int i) => i < MaxWeight ? MaxWeight - i : 1;

【讨论】:

    【解决方案2】:

    如何将源和目标用“/”分开,然后分别比较它们,这样第二个应该是更接近的一个

    C# 代码:

            var source = "x:/t/c/d";
            var sourceSplitted = source.Split('/');
            List<string> targets = new List<string>() { "a:/t/c/d", "x:/t/y/z" };
    
            for (int i = 0; i < sourceSplitted.Length; i++)
            {
                foreach (var item in targets)
                {
                    var targetSplitted = item.Split('/');
                    // Calculate levenshtein here using sourceSplitted[i] and targetSplitted[i]
                }
            }
    

    【讨论】:

      【解决方案3】:

      建议拆分路径并从后面开始给它一个反向权重,伪代码将是:

      currPath = null
      currMin = int.Max
      
      
      for (path in paths){ 
      
          var curr = 0
      
          var idx = 1;
      
          for ( x in Inverse( Split ( path ) ) ) { 
      
              curr+= idx * LevenshteinDistance( x )
              idx++;
          }
      
          if(idx < currMin)
              currPath = path;        
      }
      

      对于所有匹配的非常长的路径,它可能不起作用,但这是任何“猜测”算法都会遇到的问题,但类似的东西应该可以满足您的需求

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-11
        • 2012-05-11
        • 2014-04-14
        • 2014-08-04
        • 2015-01-28
        相关资源
        最近更新 更多