我有一个字符串比较问题 - 大多数情况下 - 按预期方式运行,但由于我的代码没有将字符串对检测为重复,所以留下大量f重复数据库插入。我认为我已经把它缩小到一个文化问题(西里尔文字符),我解决了这个问题,但现在我得到了'假阴性'(两个显然相同的字符串显示为不等于)。C#字符串比较相当于假
我看过以下类似的问题,并尝试了以下比较方法。我已经检查
相似,所以问题:
- Why does my comparison always return false?
- C# string equality operator returns false, but I'm pretty sure it should be true... What?
- String Equals() method fails even though the two strings are same in C#?
- Differences in string compare methods in C#
下面是一个字符串的例子进行比较:(标题和描述)
提要标题:埃尔斯伯格:他是一个英雄
饲料递减:丹尼尔·埃尔斯伯格告诉CNN的唐柠檬国家安全局泄密者斯诺登表现出的勇气,做了一个巨大的服务。
分贝标题:埃尔斯伯格:他是一个英雄
分贝说明:丹尼尔·埃尔斯伯格告诉CNN的唐柠檬国家安全局泄密者斯诺登表现出的勇气,有 做了一个巨大的服务。
我的应用程序将从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标题/描述不匹配。
// 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
// }
很显然,我只被使用一次以上选项中的一个 - 即matches1到matches6都有Count()==0
(它们只是测试请原谅枚举变量名)。
大多数情况下,上述选项可以正常工作,并且大部分重复都可以被检测到,但是仍然有重复滑动通过裂缝 - 我只需要了解“裂缝”是什么,所以任何建议都会受到欢迎。
我甚至尝试将字符串转换为字节数组并进行比较(前一段代码已删除,对不起)。
的Article
对象如下:
public class Article
{
public string Title;
public string Description;
}
UPDATE:
我已经试过规范化字符串以及包括IgnoreSymbols
CompareOption和我仍然得到一个假阴性(非-比赛)。我注意到的是,撇号似乎在虚假的非匹配中表现出一致的外观;所以我认为这可能是一个撇号与单引号即'vs'(等)的情况,但肯定IgnoreSymbols应该避免这种情况?
我发现一对夫妇更类似SO帖子: C# string comparison ignoring spaces, carriage return or line breaks String comparison: InvariantCultureIgnoreCase vs OrdinalIgnoreCase? 下一步:尝试使用正则表达式来剥离空格按这样的回答:https://stackoverflow.com/a/4719009/2261245
UPDATE 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值是:
:
仔细检查表明,相对于什么是通过未来的德国“eszett”字符是在数据库中不同的“勘误小胶质细胞中一种独特的TGF-β依赖的分子和 函数签名的鉴定”从进料:βVS SS
我本来期望比较1-6的至少一个来挑选起来......
有趣的是,经过一番性能比较,正则表达式的选择绝不是最慢七个。 Normalize
似乎比正则表达式更强烈! 下面是Stopwatch
持续时间为所有七时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
如果这些字符串来自数据库,则可能与知道数据库列的声明方式以及使用的排序顺序有关。 – 2014-09-12 13:19:39
“但我现在正在'误报'(两个显然相同的字符串)显示为不等于”。这不是一个'假阴性'吗? – 2014-09-12 13:20:13
还检查比较字符串的长度,可能它们包含一些不可见字符 – Charlie 2014-09-12 13:20:45