2011-11-29 55 views
18

Entiendo cómo eliminar duplicados en una lista cuando se trata de cadenas y int, etc. usando Distinct() de Linq. Pero, ¿cómo se eliminan los duplicados en función de un atributo específico de un objeto?Eliminar objetos duplicados en una lista (C#)

Por ejemplo, tengo una clase TimeMetric. Esta clase TimeMetric tiene dos atributos: MetricText y MetricTime. Tengo una lista de TimeMetrics llamada MetricList. Quiero eliminar cualquier duplicado TimeMetric con el mismo atributo MetricText. El valor TimeMetric puede ser el mismo, pero si alguno TimeMetric tiene el mismo MetricText, no debe duplicarse.

Respuesta

21

Necesita usar la segunda sobrecarga de Distinct que toma una instancia IEqualityComparer<TimeMetric> como un segundo parámetro. Definir un comparador de esta manera:

class MyComparer : IEqualityComparer<TimeMetric> 
{ 
    public bool Equals(TimeMetric x, TimeMetric y) 
    { 
     return x.MetricText.Equals(y.MetricText); 
    } 

    public int GetHashCode(TimeMetric obj) 
    { 
     return obj.MetricText.GetHashCode(); 
    } 
} 

Nota importante: El código anterior no comprueba el caso en que la propiedad MetricText es null (y suena como que podría ser, ya que es más probable que un string). Debería hacerlo y devolver 0 desde GetHashCode si MetricText es null. Por otro lado, si el tipo de MetricText es un tipo de valor, no es necesario realizar ninguna modificación.

Y luego:

var list = new List<TimeMetric> { ... }; 
var unique = list.Distinct(new MyComparer()); 
3

Usted puede utilizar Distinct overload con un IEqualityComparer.

Su método es igual para su aplicación IEqualityComparer se vería así:

bool Equals(TimeMetric x, TimeMetric y) 
{ 
    return x.MetricText.Equals(y.MetricText); 
} 
+1

Este no es correcto y solo funcionará como debería si 'MetricText' es de tipo' string' (u otro tipo que anule 'operator ==') 'Equals' se debe usar en su lugar. – Jon

+0

Supuse que era una cadena, lo cual no era una buena suposición, y actualicé la respuesta. –

14

utilizar LINQ:

var list = list 
    .GroupBy(i => i.MetricText) 
    .Select(g => g.First()) 
    .ToList(); 

o pasar en un comparador que utiliza la propiedad:

public class mtCompare : IEqualityComparer<TimeMetric> 
{ 
    public bool Equals(TimeMetric x, TimeMetric y) 
    { 
    return Equals(x.MetricText, y.MetricText); 
    } 

    public int GetHashCode(TimeMetric obj) 
    { 
    return obj.MetricText.GetHashCode(); 
    } 
} 

.... 

list.Distinct(new mtCompare()); 
Cuestiones relacionadas