.net 在字符串列表中查找与输入字符串最接近的匹配项

6g8kf2rb  于 2023-03-20  发布在  .NET
关注(0)|答案(3)|浏览(135)

我在为.net查找最接近匹配字符串的实现时遇到问题
我想匹配一个字符串列表,例如:
输入字符串:“波德斯塔瓦河流域什科瓦-波德斯塔瓦河-克罗布雷戈-翁索斯苏”
字符串列表:
布罗夫雷戈-瓦翁索斯苏地区什科瓦-波德斯塔沃瓦
什科瓦·波德斯塔沃瓦·斯佩贾尔纳
亨利卡·申凯维奇扎-瓦翁索斯苏地区什科瓦·波德斯塔沃瓦
罗穆阿尔达特劳古塔地区什科瓦波德斯塔沃瓦-瓦翁索斯祖古尔尼姆
这显然需要与“普罗尼奇纳·什科瓦·波德斯塔沃瓦·姆·B·赫罗布雷戈·瓦·翁索斯祖”相匹配。
.net有哪些可用的算法?

jmo0nnb3

jmo0nnb31#

Edit distance
编辑距离是一种通过对将一个字符串变换成另一个字符串所需的最小操作数进行计数来量化两个字符串(例如,单词)彼此有多不相似的方式。
Levenshtein distance
非正式地,两个单词之间的Levenshtein距离是将一个单词改变为另一个单词所需的单字符编辑(即插入、删除或替换)的最小数量。
Fast, memory efficient Levenshtein algorithm
C# Levenshtein

using System;

/// <summary>
/// Contains approximate string matching
/// </summary>
static class LevenshteinDistance
{
    /// <summary>
    /// Compute the distance between two strings.
    /// </summary>
    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];
    }
}

class Program
{
    static void Main()
    {
    Console.WriteLine(LevenshteinDistance.Compute("aunt", "ant"));
    Console.WriteLine(LevenshteinDistance.Compute("Sam", "Samantha"));
    Console.WriteLine(LevenshteinDistance.Compute("flomax", "volmax"));
    }
}
xam8gpfp

xam8gpfp2#

.NET不提供任何现成的东西-您需要自己实现一个Edit Distance算法。例如,您可以使用Levenshtein Distance,如下所示:

// This code is an implementation of the pseudocode from the Wikipedia,
// showing a naive implementation.
// You should research an algorithm with better space complexity.
public static int LevenshteinDistance(string s, string t) {
    int n = s.Length;
    int m = t.Length;
    int[,] d = new int[n + 1, m + 1];
    if (n == 0) {
        return m;
    }
    if (m == 0) {
        return n;
    }
    for (int i = 0; i <= n; d[i, 0] = i++)
        ;
    for (int j = 0; j <= m; d[0, j] = j++)
       ;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
            d[i, j] = Math.Min(
                Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
                d[i - 1, j - 1] + cost);
        }
    }
    return d[n, m];
}

为每个i调用LevenshteinDistance(targetString, possible[i]),然后选择LevenshteinDistance返回最小值的字符串possible[i]

yhqotfr8

yhqotfr83#

迟到了,不过我对@Ali123有个类似的要求:
“ECM”在发音上比“transcribe”更接近“Open form for ECM”
我发现了一个简单的解决方案,它适合我的用例,即比较句子,并找到具有最多共同单词的句子:

public static string FindBestMatch(string stringToCompare, IEnumerable<string> strs) {

    HashSet<string> strCompareHash = stringToCompare.Split(' ').ToHashSet();

    int maxIntersectCount = 0;
    string bestMatch = string.Empty;

    foreach (string str in strs)
    {
        HashSet<string> strHash = str.Split(' ').ToHashSet();

        int intersectCount = strCompareHash.Intersect(strHash).Count();

        if (intersectCount > maxIntersectCount)
        {
            maxIntersectCount = intersectCount;
            bestMatch = str;
        }
    }

    return bestMatch;
}

相关问题