2008-11-12 4 views
73

Учитывая следующий простой пример:LINQ Отличный оператор, игнорировать корпус?

List<string> list = new List<string>() { "One", "Two", "Three", "three", "Four", "Five" }; 

    CaseInsensitiveComparer ignoreCaseComparer = new CaseInsensitiveComparer(); 

    var distinctList = list.Distinct(ignoreCaseComparer as IEqualityComparer<string>).ToList(); 

Похоже CaseInsensitiveComparer не фактически используется, чтобы сделать сравнение без учета регистра.

Другими словами distinctList содержит такое же количество элементов, как списка. Вместо этого я бы ожидал, что, например, «Три» и «Три» считаются равными.

Я что-то упустил или это проблема с оператором Distinct?

ответ

182

StringComparer делает то, что вам нужно:

List<string> list = new List<string>() { 
    "One", "Two", "Three", "three", "Four", "Five" }; 

var distinctList = list.Distinct(
    StringComparer.CurrentCultureIgnoreCase).ToList(); 

(или инвариантного/порядковый номер/и т.д. в зависимости от данных, которые вы сравниваете)

+0

Это здорово, спасибо. – Ash 2008-11-12 06:45:50

3

[См Марк Gravells ответ, если вы хотите наиболее лаконичный подход]

После некоторого расследования и хорошей обратной связи от Брэдли Грейнджера я внедрил следующий IEqualityComparer. Это suports случай нечувствительным Distinct() заявление (просто передать экземпляр этого к Distinct оператора):

class IgnoreCaseComparer : IEqualityComparer<string> 
{ 
    public CaseInsensitiveComparer myComparer; 

    public IgnoreCaseComparer() 
    { 
     myComparer = CaseInsensitiveComparer.DefaultInvariant; 
    } 

    public IgnoreCaseComparer(CultureInfo myCulture) 
    { 
     myComparer = new CaseInsensitiveComparer(myCulture); 
    } 

    #region IEqualityComparer<string> Members 

    public bool Equals(string x, string y) 
    { 
     if (myComparer.Compare(x, y) == 0) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public int GetHashCode(string obj) 
    { 
     return obj.ToLower().GetHashCode(); 
    } 

    #endregion 
} 
+5

Вам это просто не нужно. См. Мой ответ. – 2008-11-12 06:43:56

+2

Да, ваш ответ пришел так же, как я нажимал «Разместить ответ». – Ash 2008-11-12 06:48:08

0

Вот гораздо проще вариант.

List<string> list = new List<string>() { "One", "Two", "Three", "three", "Four", "Five" }; 

var z = (from x in list select new { item = x.ToLower()}).Distinct(); 

z.Dump(); 
0

## Distinct Operator(Ignoring Case) ## 
    string[] countries = {"USA","usa","INDIA","UK","UK" }; 

    var result = countries.Distinct(StringComparer.OrdinalIgnoreCase); 

    foreach (var v in result) 
    { 
    Console.WriteLine(v); 
    } 

выход будет

USA 
    INDIA 
    UK