在字符串中查找最准确的匹配

时间:2015-02-21 14:40:47

标签: c# comparison compare match

我正在开发一种工具,通过在YouTube播放列表中搜索正确的名称来修复错误的文件名。此工具可获取YouTube播放列表视频'标题并将它们存储在列表中:

static List<string> tracksList = new List<string>();

在此列表中存储所有正确的名称后,该工具会在文件夹中执行搜索,只搜索带有&#39; .mp3&#39;的文件。扩展:

DirectoryInfo dir = new DirectoryInfo(@"C:\folder");
FileInfo[] files = musicDir.GetFiles("*.mp3", SearchOption.TopDirectoryOnly);

将所有MP3文件存储在FileInfo数组中后,它会遍历所有这些文件。此循环将逐个文件,并使用每个文件的文件名,检查哪个是trackList列表中最相似的值。我已经尝试过这个,但它确实返回一个空数组:

var trackMatch = tracksList.Where(track => track.Contains(file.Name.Replace(".mp3", "")))
                           .ToArray();

我有什么方法可以做到吗?

2 个答案:

答案 0 :(得分:2)

可以使用Levenshtein算法(more information)执行字符串比较。可以找到此算法的实现here

该函数(将计算必须更改多少个字符以包含另一个字符串)如下(取自https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C.23):

public static int LevenshteinDistance(string source, string target)
{
    if (String.IsNullOrEmpty(source))
    {
        if (String.IsNullOrEmpty(target)) return 0;
            return target.Length;
    }
    if (String.IsNullOrEmpty(target)) return source.Length;

    if (source.Length > target.Length)
    {
        var temp = target;
        target = source;
        source = temp;
    }

    var m = target.Length;
    var n = source.Length;
    var distance = new int[2, m + 1];
    // Initialize the distance 'matrix'
    for (var j = 1; j <= m; j++) distance[0, j] = j;

    var currentRow = 0;
    for (var i = 1; i <= n; ++i)
    {
        currentRow = i & 1;
        distance[currentRow, 0] = i;
        var previousRow = currentRow ^ 1;
        for (var j = 1; j <= m; j++)
        {
            var cost = (target[j - 1] == source[i - 1] ? 0 : 1);
            distance[currentRow, j] = Math.Min(Math.Min(
                distance[previousRow, j] + 1,
                distance[currentRow, j - 1] + 1),
                distance[previousRow, j - 1] + cost);
        }
    }
    return distance[currentRow, m];
}

因此,如果使用前一个函数将输入字符串与trackList中存储的每个字符串进行比较,我们将获得Levenshtein值:最低值将表示它是最相似的:

static List<int> matchList = new List<int>();
foreach (string Track in tracksList)
{
    matchList.Add(LevenshteinDistance(Track, "Dailucia   Where My Heart Matches The Beat (Ft Poprebel) [FULL HQ + HD]"));
}
string match = tracksList.ElementAt(matchList.IndexOf(matchList.Min()));

答案 1 :(得分:1)

这是一项非常重要的任务。

问题当然是文件名中的错误可以是任何,从拼写错误到遗漏单词再添加空格。

这意味着任何字符都可能以任何方式受到影响。

因此,简单的Contains甚至智能RegEx都不会可靠地运作。

我会将文件名拆分为单词,并对列表标题中找到的单词数量进行计数。数量最多的人有最好的机会成为正确的人。

我还会尝试一个半自动程序,在那里我可以获得按命中计数排序的选项,然后可以确认,纠正或通过..