2011-11-29 32 views
18

Rozumiem więc sposób usuwania duplikatów na liście, jeśli chodzi o ciągi i int, itp. Przy użyciu Distinct() z Linq. Ale jak usunąć duplikaty na podstawie określonego atrybutu obiektu? Na przykład mam klasę TimeMetric. Ta klasa TimeMetric ma dwa atrybuty: MetricText i MetricTime. Mam listę TimeMetrics o nazwie MetricList. Chcę usunąć wszystkie duplikaty TimeMetric z tym samym atrybutem MetricText. Wartość TimeMetric może być taka sama, ale jeśli jakikolwiek TimeMetric ma taką samą wartość , musi być niepowielany.Usuwanie duplikatów obiektów z listy (C#)

Odpowiedz

21

Musisz użyć drugiego przeciążenia z Distinct, które pobiera instancję IEqualityComparer<TimeMetric> jako drugi parametr. Zdefiniuj porównywarka tak:

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

Ważna uwaga: Powyższy kod nie sprawdza w przypadku, gdy właściwość MetricText jest null (i brzmi to jak to może być, ponieważ jest to najprawdopodobniej string). Powinieneś to zrobić i zwrócić 0 z GetHashCode, jeśli MetricText jest null. Z drugiej strony, jeśli typ MetricText jest typem wartości, nie trzeba wykonywać żadnych modyfikacji.

A potem:

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

Można użyć Distinct overload z IEqualityComparer.

Twoja metoda equals do realizacji IEqualityComparer będzie wyglądać następująco:

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

ten jest niepoprawny i działa tylko tak, jak powinien, jeśli 'MetricText' jest typu' string' (lub innego typu, który przesłania 'operator =='). Zamiast tego należy użyć 'Equals'. – Jon

+0

Zakładam, że był to ciąg znaków, który nie był dobrym założeniem i zaktualizował odpowiedź. –

14

używać LINQ:

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

Albo przechodzą w comparer który wykorzystuje właściwość:

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()); 
Powiązane problemy