C#字符串比较等同于假

我有一个字符串比较问题 - 大多数情况下 - 的行为如预期的那样,但是留下大量f重复的数据库插入,因为我的代码没有将字符串对检测为重复。

我以为我已经把它缩小到一个文化问题(西里尔字符),我解决了这个问题,但现在我得到了'假阴性'(两个显然相同的字符串显示为不等于)。

我看过以下类似的问题,并尝试了以下比较方法。

类似的问题,我已经检查:

  • 为什么我的比较总是返回错误?
  • C#字符串相等运算符返回false,但我很确定它应该是真的......什么?
  • 即使两个字符串在C#中相同,String Equals()方法也会失败?
  • C#中字符串比较方法的差异
  • 这是一个比较字符串的例子:(标题和描述)

    饲料标题: Ellsberg:他是英雄

    feed desc:丹尼尔埃尔斯伯格告诉CNN的唐柠檬,NSA的泄密者爱德华斯诺登表现出勇气,做了一个巨大的服务。

    db标题: Ellsberg:他是英雄

    db desc:丹尼尔埃尔斯伯格告诉美国有线电视新闻网的唐·柠檬,国家安全局的泄密者爱德华斯诺登表现出勇气,做了一项巨大的服务。

    我的应用程序将从RSS提要中提取的值与我在数据库中的值进行比较,并且应该只插入“新”值。

    //fetch existing articles from DB for the current feed:
        List<Article> thisFeedArticles = (from ar in entities.Items
                                          where (ar.ItemTypeId == (int)Enums.ItemType.Article) && ar.ParentId == feed.FeedId
                                          && ar.DatePublished > datelimit
                                          select new Article
                                          {
                                               Title = ar.Title, 
                                               Description = ar.Blurb
                                          }).ToList();
    

    下面的比较中的每个人都显示不匹配Ellsberg标题/描述。 即match1到matches6都有Count()==0

    (请原谅枚举的变量名称 - 它们仅用于测试)

       // comparison methods 
    CompareOptions compareOptions = CompareOptions.OrdinalIgnoreCase;
    CompareOptions compareOptions2 = CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace;
    //1
    IEnumerable<Article> matches = thisFeedArticles.Where(b =>
        String.Compare(b.Title.Trim().Normalize(), a.Title.Trim().Normalize(), CultureInfo.InvariantCulture, compareOptions) == 0 &&
        String.Compare(b.Description.Trim().Normalize(), a.Description.Trim().Normalize(), CultureInfo.InvariantCulture, compareOptions) == 0
        );
    
    //2
    IEnumerable<Article> matches2 = thisFeedArticles.Where(b =>
        String.Compare(b.Title, a.Title, CultureInfo.CurrentCulture, compareOptions2) == 0 &&
        String.Compare(b.Description, a.Description, CultureInfo.CurrentCulture, compareOptions2) == 0
        );
    
    //3
    IEnumerable<Article> matches3 = thisFeedArticles.Where(b =>
        String.Compare(b.Title, a.Title, StringComparison.OrdinalIgnoreCase) == 0 &&
        String.Compare(b.Description, a.Description, StringComparison.OrdinalIgnoreCase) == 0
        );
    
    //4
    IEnumerable<Article> matches4 = thisFeedArticles.Where(b =>
        b.Title.Equals(a.Title, StringComparison.OrdinalIgnoreCase) &&
        b.Description.Equals(a.Description, StringComparison.OrdinalIgnoreCase)
        );
    
    //5
    IEnumerable<Article> matches5 = thisFeedArticles.Where(b =>
        b.Title.Trim().Equals(a.Title.Trim(), StringComparison.InvariantCultureIgnoreCase) &&
        b.Description.Trim().Equals(a.Description.Trim(), StringComparison.InvariantCultureIgnoreCase)
        );
    
    //6
    IEnumerable<Article> matches6 = thisFeedArticles.Where(b =>
        b.Title.Trim().Normalize().Equals(a.Title.Trim().Normalize(), StringComparison.OrdinalIgnoreCase) &&
        b.Description.Trim().Normalize().Equals(a.Description.Trim().Normalize(), StringComparison.OrdinalIgnoreCase)
        );
    
    
        if (matches.Count() == 0 && matches2.Count() == 0 && matches3.Count() == 0 && matches4.Count() == 0 && matches5.Count() == 0 && matches6.Count() == 0 && matches7.Count() == 0)
        {
        //insert values
        }
    
        //this if statement was the first approach
        //if (!thisFeedArticles.Any(b => b.Title == a.Title && b.Description == a.Description)
        // {
        // insert
        // }
    

    显然,我一次只使用上述选项之一。

    大多数情况下,上述选项可以工作,并且大部分重复都可以检测到,但仍然有重复的部分滑过裂缝 - 我只需要了解“裂缝”是什么,因此任何建议都会受到欢迎。

    我甚至尝试将字符串转换为字节数组并进行比较(前一段代码已删除,对不起)。

    Article对象如下:

        public class Article
        {
            public string Title;
            public string Description;
        }
    

    更新:

    我试过规范化字符串以及包括IgnoreSymbols CompareOption,并且我仍然得到一个错误的否定(不匹配)。 我注意到的是,撇号似乎在虚假的非匹配中表现出一致的外观; 所以我认为这可能是一个撇号与单引号的情况,即'vs'(等),但肯定IgnoreSymbols应该避免这种情况?

    我发现了几个更类似的SO帖子:C#字符串比较忽略空格,回车或换行字符串比较:InvariantCultureIgnoreCase与OrdinalIgnoreCase? 下一步:尝试使用正则表达式根据此答案去掉空白区域:https://stackoverflow.com/a/4719009/2261245

    更新2在6比较后,STILL没有返回任何匹配,我意识到必须有另一个因素歪曲结果,所以我尝试了以下

    //7
    IEnumerable<Article> matches7 = thisFeedArticles.Where(b =>
        Regex.Replace(b.Title, "[^0-9a-zA-Z]+", "").Equals(Regex.Replace(a.Title, "[^0-9a-zA-Z]+", ""), StringComparison.InvariantCultureIgnoreCase) &&
        Regex.Replace(b.Description, "[^0-9a-zA-Z]+", "").Equals(Regex.Replace(a.Description, "[^0-9a-zA-Z]+", ""), StringComparison.InvariantCultureIgnoreCase)
        );
    

    这会发现其他人错过的比赛!

    下面的字符串通过了所有6个比较,但不是7号:

    a.Title.Trim().Normalize()a.Title.Trim()都返回:

    “更正:在小胶质细胞中鉴定独特的TGF-β依赖性分子和功能标记”

    DB中的值是:

    “更正:在小胶质细胞中鉴定独特的TGF-β依赖性分子和功能标记”

    更仔细的检查表明德国人的eszett性格在数据库中与从饲料中获得的数据不同:βvsß

    我本来期望至少有一次比较1-6挑选出来......

    有趣的是,经过一些性能比较之后,Regex选项绝不是七个中最慢的。 Normalize看起来比正则表达式要密集得多! 当thisFeedArticles对象包含12077个项目时,以下是所有七个Stopwatch持续时间

    所用时间:00:00:00.0000662
    所用时间:00:00:00.0000009
    所用时间:00:00:00.0000009
    所用时间:00:00:00.0000009
    所用时间:00:00:00.0000009
    所用时间:00:00:00.0000009
    所用时间:00:00:00.0000016


    Unicode字符串可以是“二元”不同的,即使它们在“语义上”相同。

    尝试规范化你的字符串。 有关更多信息,请参阅http://msdn.microsoft.com/en-us/library/System.String.Normalize.aspx

    链接地址: http://www.djcxy.com/p/81487.html

    上一篇: C# String Comparison equates to false

    下一篇: Could not post JSON requests to GCM after 6 attempts