我认为这是一个文化差异问题(西里尔字母),我已经解决了它,但现在我得到了“假阴性”(两个明显相等的字符串显示为不相等)。
我已经查看了以下类似的问题,并尝试了以下的比较方法。
我查阅了类似的SO问题:
- 为什么我的比较总是返回false?
- C#字符串相等运算符返回false,但我非常确定它应该是true...怎么回事?
- C#中String Equals()方法失败,即使两个字符串相同?
- C#中字符串比较方法的差异
以下是被比较的字符串示例:(标题和描述)
feed title: 艾尔斯伯格:他是英雄
feed desc: 丹尼尔·艾尔斯伯格告诉CNN的唐·莱蒙,NSA泄密者爱德华·斯诺登表现出了勇气,做出了巨大贡献。
db title: 艾尔斯伯格:他是英雄
db desc: 丹尼尔·艾尔斯伯格告诉CNN的唐·莱蒙,NSA泄密者爱德华·斯诺登表现出了勇气,做出了巨大贡献。
我的应用程序将从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的标题/描述。即matches1到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# string comparison ignoring spaces, carriage return or line breaks String comparison: InvariantCultureIgnoreCase vs OrdinalIgnoreCase? 下一步:尝试使用正则表达式去除空格,如此答案所述:https://dev59.com/H2445IYBdhLWcg3wustT#4719009
更新2: 经过6次比较仍然没有匹配,我意识到必须有另一个因素扭曲了结果,所以我尝试了以下操作。
//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-β依赖性分子和功能特征签名"
数据库中的值为:
"勘误:在小胶质细胞中鉴定了一种独特的TGF-ß依赖性分子和功能特征签名"
仔细检查后发现,德语“eszett”字符在数据库中与来自源的字符不同:β vs ß
我本来期望至少有一个比较1-6能够捕捉到这一点...
有趣的是,在一些性能比较之后,正则表达式选项并不是七个选项中最慢的。 Normalize
显然比正则表达式更加密集!以下是当 thisFeedArticles
对象包含12077个项目时的所有七个计时器持续时间。
已过时间: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