2009-06-23 4 views
1

J'ai un problème que je suis sûr que quelqu'un ici a résolu plus facilement que ce que je pense à faire. J'ai une liste qui a un nom et un numéro. Le nom est requis et pourrait être en double et le numéro ne pourrait être qu'un, mais pas obligatoire.Comment changer la foncalité distincte dans .NET?

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

En ce moment je joue un list.Distinct() sur la partie du nom, mais il ne se soucie pas de la section numérique.

newlist = oldlist.Distinct().ToList(); 

Si un nom qui est en double a un numéro, je veux garder celui avec le numéro, ce qui ne se produit pas. Le cas de deux mêmes noms et deux numéros différents ne se produira pas. Des idées?

Encore une chose: En ce moment, je ne me soucie pas du tri puisque je m'en occupe.

J'ajoute tout le code pour une meilleure visibilité de l'équipe StackOverflow:

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

Au-dessus de la mise en œuvre IEqualityComparer et au-dessous de l'appel Distinct.

 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

Vous pouvez fournir du code supplémentaire (qu'est-ce que 'oldList', à quoi ressemble la classe personnalisée, etc.). – Groo

+0

Merci Groo pour votre commentaire. J'ai ajouté tout mon code lié à cette question, s'il vous plaît laissez-moi savoir si cela aide. – Geo

Répondre

0

essayer mettre en œuvre un IEqualityComparer pour votre type, et en passant comme paramètre à Distinct (je suppose que votre liste tenir une Tuple de ficelle et un Nullable int (Tuple est pas une classe .NET - jusqu'à .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 
     } 

puis

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

Je pense que cela va garder "A" et "A2", ce qui n'est pas ce que l'OP voulait. – Groo

+0

x.a.Equals (x.a) J'espère bien que c'est toujours vrai ou jette une nullreferenceexception :) –

+0

Ce n'était pas vraiment un code prêt pour la production - juste une direction à prendre en compte :) –

0

Si la liste est composée d'objets qui ressemblent à ceci:

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

où le nombre 0 n'a indiqué aucun nombre. Vous obtenez le résultat en triant d'abord, puis en faisant distinct. Distinct garde une hashtable de chaque élément rencontré et vérifie l'existence des éléments suivants. Alors:

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

Vous pouvez utiliser groupant:

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

Avec MyObject être:

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

Si vous avez un élément répété avec des chiffres différents (comme {A, 1} ({A, 2}), le Max est choisi.

Questions connexes