2008-11-12 16 views
73

Biorąc pod uwagę następujący prosty przykład:LINQ Odrębny operator, ignoruj ​​sprawę?

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(); 

Wydaje się, że CaseInsensitiveComparer nie jest faktycznie wykorzystywany do zrobienia bez uwzględniania wielkości liter porównania.

Innymi słowy distinctList zawiera tę samą liczbę pozycji co lista. Zamiast tego oczekiwałbym na przykład, że "Trzy" i "trzy" będą uważane za równe.

Czy brakuje mi czegoś lub czy jest to problem z operatorem Distinct?

Odpowiedz

182

StringComparer robi to, co trzeba:

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

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

(lub niezmienny/porządkowa/etc w zależności od danych, które porównują)

+0

To świetnie, dzięki. – Ash

3

[Zobacz Marc Gravells odpowiedź, jeśli chcesz najbardziej zwięzły podejście]

Po przeprowadzeniu dochodzenia i uzyskaniu pozytywnych opinii od Bradleya Grainger'a zaimplementowałem następujący program IEqualityComparer. To suports przypadek niewrażliwe Wyraźny() oświadczenie (wystarczy przejść instancję to do operatora 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

Po prostu tego nie potrzebujesz. Zobacz moją odpowiedź. –

+2

Tak, Twoja odpowiedź dotarła dokładnie tak, jak kliknąłem "Opublikuj swoją odpowiedź". – Ash

+0

Na pewno pamiętam z <20 sekundami. Mimo to, wdrożenie czegoś takiego jak IEqualityComparer jest nadal przydatnym ćwiczeniem, choćby dla zrozumienia jego działania ... –

0

Tu jest o wiele prostsza wersja.

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); 
    } 

wyjście będzie

USA 
    INDIA 
    UK 
+3

Należy unikać publikowania fragmentów kodu bez objaśnienia. Edytuj swoją odpowiedź i dodaj do niej treść. Dzięki. – Clijsters