2013-04-29 165 views
2

我有大量的字符串,包括許多重複項。重要的是所有的副本都有相同的外殼。所以這集將在測試不及格:確定HashSet <String>是否包含不同的字符串

String[] strings = new String[] { "a", "A", "b", "C", "b" }; 

....但這個測試將通過:當我通過strings每個字符串重複

String[] strings = new String[] { "A", "A", "b", "C", "b" }; 

,我的計劃是如何可以看到A是不區分大小寫重複的a(因此失敗),但允許通過重複b

+1

你的標題說'HashSet'和你的問題有'數組',是缺少的東西? – Habib 2013-04-29 05:41:51

+0

如果您使用Equals來檢查兩個字符串是否相等,那麼會有一個重載,它會接收一個StringComparison枚舉值。你可能想使用'StringComparison.OrdinalIgnoreCase'。如果您需要使用'HashSet '(或'Dictionary ')使用特定比較,則使用接受「IEqualityComparer 」的實例構造函數構造'HashSet <>'(等等)的實例。在這種情況下,你可能想使用比較器'StringComparer.OrdinalIgnoreCase'。 – 2013-04-29 05:52:21

回答

3

一種簡單的方法是創建兩個集 - 一個使用不區分大小寫的字符串比較器,另一個使用區分大小寫的字符串比較器。 (我不清楚你是否想要一個文化敏感的字符串,或不是在哪種文化中。)

施工後,如果兩套具有不同的尺寸(Count),那麼必須有一些相等的元素通過不區分大小寫的比較,但不區分大小寫。

因此,像:

public static bool AllDuplicatesSameCase(IEnumerable<string> input) 
{ 
    var sensitive = new HashSet<String>(input, StringComparer.InvariantCulture); 
    var insensitive = new HashSet<String>(input, 
      StringComparer.InvariantCultureIgnoreCase); 
    return sensitive.Count == insensitive.Count; 
} 
+0

+1。簡單而不需要任何自定義代碼! – 2013-04-29 06:00:19

+0

這將起作用,因爲一個比較器應該比另一個比較「嚴格」,這就是邏輯蘊涵_if_ InvariantCulture聲明兩個字符串是相等的,然後InvariantCultureIgnoreCase也會聲明它們是平等的。在選擇此解決方案之前,需要考慮兩個主要問題。首先,這會創建源'輸入'的兩個完整副本。如果「輸入」很大,這可能會浪費內存。其次,這遍歷整個源碼兩次。如果在「輸入」列表的早期有一個「反例」,其他一些解決方案可能會退出並且不會繼續迭代。 – 2013-04-29 07:46:20

+0

@JeppeStigNielsen:同意。我絕對是爲了簡單而不是其他任何事情。 – 2013-04-29 07:48:26

0

你可以明確地檢查每一個條目。

static bool DuplicatesHaveSameCasing(string[] strings) 
{ 
    for (int i = 0; i < strings.Length; ++i) 
    { 
    for (int j = i + 1; j < strings.Length; ++j) 
    { 
     if (string.Equals(strings[i], strings[j], StringComparison.OrdinalIgnoreCase) 
     && strings[i] != strings[j]) 
     { 
     return false; 
     } 
    } 
    } 
    return true; 
} 

評論:我選擇使用序數比較。請注意,!=運算符使用序數和區分大小寫的比較。把它變成一些與文化相關的比較是相當微不足道的。

0

另一種選擇使用LINQ。

    //Group strings without considering case 
bool doesListPass = strings.GroupBy(s => s.ToUpper()) 
        //Check that all strings in each group has the same case 
        .All(group => group.All(s => group.First() == s)); 

        //Group strings without considering case 
IEnumerable<string> cleanedList = strings.GroupBy(s => s.ToUpper()) 
        //Check that all strings in each group has the same case 
        .Where(group => group.All(s => group.First() == s)) 
        //Map all the "passing" groups to a list of strings 
        .SelectMany(g => g.ToList()); 

注意:您可以根據需要使用ToUpper()或ToUpperInvariant()。

相關問題