2009-06-23 2 views
1

Ich habe ein Problem, dass ich sicher bin, dass jemand hier draußen einfacher gelöst hat, als was ich denke, zu tun. Ich habe eine Liste mit Namen und Nummer. Name ist erforderlich und könnte doppelt sein und die Nummer könnte nur eins sein, aber nicht erforderlich.Wie ändere ich Distinct Funcationality in .NET?

|name|number| 
|A |2  | 
|A |  | 
|B |  | 
|C |  | 
|C |  | 
|D |4  | 
------------- 

In diesem Moment bin ich die Durchführung einer list.Distinct() auf dem Namensteil, aber es über die Anzahl Abschnitt kümmert sich nicht darum.

Wenn ein Name, der Duplikat ist, eine Nummer hat, möchte ich den einen mit der Nummer behalten, was nicht passiert. Der Fall von zwei gleichen Namen und zwei verschiedenen Zahlen wird nicht passieren. Irgendwelche Ideen?

Noch eine Sache: In diesem Moment interessiere ich mich nicht für das Sortieren, da distinct darauf achten.

Ich füge den gesamten Code für eine bessere Sichtbarkeit des Stackoverflow Team:

class _ClientComparer : IEqualityComparer<_Client> 
{ 
    #region IEqualityComparer<_Client> Members 

    public bool Equals(_Client x, _Client y) 
    { 
     if ((x.ClientNumber != 0) && (y.ClientNumber != 0))//Both clients with numbers 
      if (x.ClientNumber == y.ClientNumber)//both clients number the same then same clients. 
       return true; 
      else //if not the same they are different 
       return false; 
     else if (x.ClientName == y.ClientName) 
      return true; 
     else 
      return false; 
    } 

    public int GetHashCode(_Client obj) 
    { 
     if (obj.ClientNumber != 0) 
      return obj.ClientNumber.GetHashCode(); 
     else 
      return obj.ClientName.GetHashCode(); 
    } 

Oberhalb der IEqualityComparer Implementierung und unterhalb der Distinct Anruf.

 public List<_Client> CollectAllClients() 
    { 
     List<_Client> ClientList = new List<_Client>(); 
     while (this.Read()) 
     { 
      if (GetClientNumber() != 0) 
       ClientList.Add(CreateClientInstance()); 
      else 
       ClientList.AddRange(CreateClientsInstance()); 
     } 
     ClientList = ClientList.Distinct<_Client>(new _ClientComparer()).ToList<_Client>() ; 
     return ClientList; 
    } 
+0

Sie könnten zusätzlichen Code angeben (was genau ist 'oldList', wie sieht die benutzerdefinierte Klasse aus etc.). – Groo

+0

Danke Groo für Ihren Kommentar. Ich habe meinen gesamten Code zu dieser Frage hinzugefügt. Bitte lassen Sie mich wissen, ob dies hilfreich ist. – Geo

Antwort

0

versuchen, einen IEqualityComparer für Ihre Art der Umsetzung, und es als Parameter an Distinct vorbei (Ich gehe davon aus, dass Ihre Liste ein Tuple von Zeichenfolge halten und eine Nullable int (Tuple ist keine .NET-Klasse - bis .Net 4,0)

 private class c : IEqualityComparer<Tuple<string,int?>> 
     { 

      #region IEqualityComparer<Tuple<string,int?>> Members 

      public bool Equals(Tuple<string, int?> x, Tuple<string, int?> y) 
      { 
       if (x.a.Equals(x.a) && x.b.Equals(y.b)) 
        return true; 
       return false; 
      } 

      public int GetHashCode(Tuple<string, int?> obj) 
      { 
       throw new NotImplementedException(); 
      } 

      #endregion 
     } 

und dann

List<Tuple<string,int?>> list; 
..... 
list.Distinct(new c()); 
+0

Ich denke, das wird sowohl "A" als auch "A2" behalten, was OP nicht wollte. – Groo

+0

x.a.Equals (x.a) Ich hoffe, das ist immer entweder wahr oder löst eine Nullreferenzausnahme :) –

+0

Es war nicht wirklich ein produktionsfertiger Code - nur eine Richtung zum Nachdenken :) –

0

Wenn die Liste von Objekten zusammengesetzt ist, die wie folgt aussehen:

class Record : IEquatable<Record> 
{ 
    public string Name { get; set; } 
    public int Number { get; set; } 

    public bool Equals(Record r) 
    { 
     if (r == null) return false; 
     return this.Name.Equals(r.Name) && this.Number.Equals(r.Number); 
    } 
} 

wo Nummer 0 keine Nummer angegeben. Sie erzielen das Ergebnis, indem Sie zuerst sortieren, dann unterscheiden. Distinct behält eine Hashtabelle für jedes gefundene Element und prüft, ob es in nachfolgenden Elementen vorhanden ist. Also:

var newList = oldList.OrderByDescending(x => x.Number).Distinct(); 
1

können Sie Gruppierung verwenden:

 List<MyObject> tests = new List<MyObject>() 
     { 
      new MyObject {Name = "A", Number = 2 }, 
      new MyObject {Name = "A", Number = null }, 
      new MyObject {Name = "B", Number = null}, 
      new MyObject {Name = "C", Number = null}, 
      new MyObject {Name = "C", Number = null}, 
      new MyObject {Name = "D", Number = 4} 
     }; 

     var qry = from t in tests 
        group t by t.Name into g 
        select g.Max(); 

     qry.ToList(); 

Mit MyObject Wesen:

public class MyObject : IComparable<MyObject> 
{ 
    public string Name { get; set; } 
    public int? Number { get; set; } 

    public int CompareTo(MyObject other) 
    { 
     return Comparer<int?>.Default.Compare(this.Number, other.Number); 
    } 
} 

Wenn Sie ein wiederholtes Element mit einem unterschiedlichen Anzahl (wie {A, 1} , {A, 2}), wird die Max gewählt.