C#比较字符串和缩写

时间:2019-01-10 18:03:32

标签: c# string .net-core comparison string-comparison

我正在尝试将完整字符串与其缩写版本进行比较,并根据其相似性返回分数。

这是一个例子:

  

Quart Vara Civel Santana de Parnaiba

以及可能的缩写

  

Qta VC Sta Parnaiba

     

Q V C Sta Pba

     

4 VC Sta Parnaiba

我尝试使用FuzzyStrings dll来执行此操作,但是当涉及第二个和第三个示例的严重缩写时,效果不佳。

关于如何处理此问题的任何想法?

1 个答案:

答案 0 :(得分:4)

使用this answer中的Jaro-Winkler距离类,该类优先考虑匹配的前缀,并将每个缩写成分与短语单词进行比较(选择最大匹配以补偿跳过的单词),我们可以编写这些扩展名:

public static class StringExt {
    public static double JaroWinklerDistance(this string s1, string s2) => JaroWinkler.proximity(s1, s2);

    private static Regex AbbrevSplitRE = new Regex(@" |(?=\p{Lu})", RegexOptions.Compiled);
    public static double AbbrevSimilarity(this string abbrev, string phrase) {
        var phraseWords = phrase.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        return AbbrevSplitRE.Split(abbrev)
                            .Where(aw => !String.IsNullOrEmpty(aw))
                            .Zip(Enumerable.Range(0, phraseWords.Length),
                                 (aw, pwp) => Enumerable.Range(pwp, phraseWords.Length-pwp).Select(n => aw.JaroWinklerDistance(phraseWords[n])).Max()
                            )
                            .Sum() / phraseWords.Length;
    }    
}

注意:正则表达式在每个空格或大写字母处定义缩写成分。

然后,我们可以将abbrevs中的每个缩写与原始phrase进行比较:

var ans = abbrevs.Select(Abbrev => new { Abbrev, Similarity = Abbrev.AbbrevSimilarity(phrase) });

以您的示例为例,我得到以下答案:

      Abbrev        |     Similarity
Qta VC Sta Parnaiba | 0.65001322751322754
Q V C Sta Pba       | 0.60371693121693126
4 VC Sta Parnaiba   | 0.53890211640211649

我可能会为较短的缩写添加一个权重,具体取决于我的最终目的。