2013-06-07 12 views
27

ich nicht in der Lage bin, die Duplikate aus der Sammlung zu entfernen, habe ich noch IEqualityComparer für die Klasse Mitarbeiter implementiert i immer bin nicht die AusgabeWie Duplikate aus der Sammlung entfernen IEqualityComparer, LinQ Distinct

static void Main(string[] args) 
    { 
     List<Employe> Employeecollection = new List<Employe>(); 

     Employeecollection.Add(new Employe("abc","def")); 
     Employeecollection.Add(new Employe("lmn","def")); 
     Employeecollection.Add(new Employe("abc", "def")); 

     IEnumerable<Employe> coll = Employeecollection.Distinct(new Employe()); 

     foreach (Employe item in coll) 
     { 
      Console.WriteLine(item.fName + " " + item.lName); 
     } 

    } 

Die Folgenden wird die Employee-Klasse Umsetzung, hier implementiert i IEqualityComparer

class Employe : IEqualityComparer<Employe> 
{ 
    public string fName { get; set; } 
    public string lName { get; set; } 

    public Employe() 
    { 

    } 

    public Employe(string firstName, string LastName) 
    { 
     this.fName = firstName; 
     this.lName = LastName; 
    } 

    #region IEqualityComparer<pcf> Members 

    public bool Equals(Employe x, Employe y) 
    { 
     if (x.fName == y.fName && x.lName == y.lName) 
     { 
      return true; 
     } 

     return false; 
    } 

    public int GetHashCode(Employe obj) 
    { 
     return obj.GetHashCode(); 
    } 

    #endregion 
} 

Antwort

79

IEqualityComparer vergessen und nur Linq direkt verwenden:

EmployeeCollection.GroupBy(x => new{x.fName, x.lName}).Select(g => g.First()); 
+0

Can u erklären Sie bitte die oben ein i GroupBy verstehen, aber was Select ist (g => g.First() – Gun

+6

Der GroupBy Operation erhalten Sie eine IEnumerable von [IGrouping] (http://msdn.microsoft.com/en-us/library/bb344977.aspx) Elemente (die auch IEnumerables sind.) Im Falle Ihres Beispiels gibt es zwei Elemente im äußeren IEnumerable: ein IGrouping mit zwei Einträgen für jeden "abc", "def"; ein weiteres IGrouping mit einem Eintrag für "lmn", "def". Der Operator First() nimmt das erste Element aus den inneren IGrouping IEnumerables. – avanek

+0

für Logik mit mehreren Eigenschaften, die Sie gruppieren müssen auf allen Eigenschaften, die langsamer als der xor-Vergleich laufen werden –

4

Sie benötigen GetHashCode Methode in Ihren Mitarbeitern außer Kraft zu setzen. Du hast das nicht getan. Ein Beispiel für eine gute Hash-Verfahren ist unten angegeben: (erzeugt durch ReSharper)

public override int GetHashCode() 
{ 
    return ((this.fName != null ? this.fName.GetHashCode() : 0) * 397)^(this.lName != null ? this.lName.GetHashCode() : 0); 
} 

jetzt nach Distinct genannt wird, foreach-Schleife druckt:

abc def 
lmn def 

In Ihrem Fall Sie Objektklasse aufrufen GetHashCode, die nichts über interne Felder weiß.

Eine einfache Notiz, MoreLINQ enthält DistinctBy Erweiterung Methode, die Sie tun können:

IEnumerable<Employe> coll = 
Employeecollection.DistinctBy(employee => new {employee.fName, employee.lName}); 

Anonyme Objekte haben korrekte Implementierung für beide GetHashCode und Equals Methoden.

5

Hier ist eine gute tutorial

public int GetHashCode(Employe obj) 
    { 
     return obj.fname.GetHashCode()^obj.lname.GetHashCode(); 
    } 
+2

Sie sollten GetHashCode niemals implementieren, ohne auch Gleichheitselemente zu implementieren. GetHashCode sollte auch eine Überschreibung sein. Bedenken Sie auch, dass * '' xor 'Verteilungsprobleme verursachen oder verschlimmern kann, wenn Datenstrukturen redundant sind. * *: Http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines- and-rules-for-gethashcode.aspx – spender

2

Die Hash-Code-Implementierung ist nicht korrekt:

public override int GetHashCode() 
{ 
    return 13 * fName.GetHashCode() + 7 * lName.GetHashCode(); 
} 
+1

ist es in Ordnung, 'NullReferenceException' in' GetHashCode' zu ​​erhalten, wenn eines der Objektfelder null ist? –

+0

Es ist definitiv nicht - ich dachte nur, ich könnte klarstellen, dass "Hashcodes sollten gleich sein, wenn gleich sind" Tatsache, als auf die Null-Prüfungen konzentrieren. Aber ja, du hast Recht. – aquaraga

-1
public int GetHashCode(Employe obj) 
{ 
    return obj.GetHashCode(); 
} 

Hierzu Methode, geben Sie einen Hashcode der Eigenschaften, die Sie für Gleichheit vergleichen, anstelle des Objekts selbst zurück. Der Hashcode der Objekte wird immer false sein, so dass Ihre Liste niemals nach Duplikaten gefiltert wird.

0

Auch sieht es so aus, als ob Sie durch Vergleich statt Inhalt vergleichen, daher funktioniert die Vergleichsfunktion nicht.

ändern Sie es zu verwenden .Equals() statt == und es sollte funktionieren. Beispiel unten:

#region IEqualityComparer<pcf> Members 

public bool Equals(Employe x, Employe y) 
{ 
    if (x.fName.Equals(y.fName) && x.lName.Equals(y.lName)) 
    { 
     return true; 
    } 

    return false; 
} 

public int GetHashCode(Employe obj) 
{ 
    return obj.GetHashCode(); 
} 

#endregion 
+1

Der ==-Operator funktioniert problemlos für Zeichenfolgen in C#. Das Problem liegt in der GetHashCode() - Implementierung. – Fredrik

Verwandte Themen