2008-11-12 7 views
73

Dado el siguiente ejemplo:LINQ Operador distintivo, ignora el caso?

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

Parece que el CaseInsensitiveComparer en realidad no se está utilizando para hacer una comparación entre mayúsculas y minúsculas.

En otras palabras distinctList contiene la misma cantidad de elementos como lista. En cambio, esperaría, por ejemplo, que "Tres" y "Tres" se consideren iguales.

¿Me falta algo o es esto un problema con el operador Distinct?

Respuesta

182

StringComparer hace lo que necesita:

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

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

(o invariante/ordinal/etc dependiendo de los datos que se están comparando)

+0

Eso es grande, gracias. – Ash

3

[Véase la respuesta Marc Gravells si desea que el enfoque más concisa]

Después de algunas investigaciones y buenos comentarios de Bradley Grainger, he implementado el siguiente IEqualityComparer. Se suports una declaración insensibles distintas() caso (sólo tiene que pasar una instancia de esta al operador distinto):

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

Simplemente no necesita esto. Ver mi respuesta –

+2

Sí, su respuesta llegó justo cuando estaba haciendo clic en "Publicar su respuesta". – Ash

+0

Ciertamente estaban con <20 segundos el uno del otro, recuerdo. Aún así, implementar algo como IEqualityComparer sigue siendo un ejercicio útil, aunque solo sea para entender cómo funciona ... –

0

Aquí es una versión mucho más sencilla.

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

salida será

USA 
    INDIA 
    UK 
+3

Por favor, evite publicar fragmentos de código sin explicación. Edita tu respuesta y agrega un cuerpo a ella. Gracias. – Clijsters