我有一個字符串比較問題 - 大多數情況下 - 按預期方式運行,但由於我的代碼沒有將字符串對檢測爲重複,所以留下大量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