2017-10-12 6 views
2

J'ai une liste C# avec 2 champs. Je dois trouver des doublons basés sur Field1 mais exclure les doublons où Field2 est également la même pour la paire donnée d'éléments en double. En d'autres termes:Trouver des doublons dans la liste et exclure des éléments basés sur un autre champ

Field1 Field2 
------------- 
0  0 
0  1 

devrait être dans le résultat, alors que

Field1 Field2 
------------- 
0  1 
0  1 

ne devrait pas être le résultat.
Jusqu'à présent, j'ai obtenu ceci:

dups = myList 
    .AsParallel() 
    .GroupBy(x => x.field1) 
    .Where(x => x.Count() > 1) 
    .Select(x => x.Key); 

Mais je ne sais pas comment exclure en fonction de Field2.

+0

Que voulez-vous dire par 'où Field2 est également le même'? Vous voulez dire que vous voulez exclure les résultats où 'Field2' est dupliqué, mais ayant le même' Field1'? – GeorgeChond

+0

Oui, c'est exactement ce que j'essaie de faire. – Manngo

+0

Quand il y a des entrées dupliquées, voulez-vous en garder une (une ligne '0 1' au lieu de deux) ou pour éviter de les obtenir toutes (pas de ligne' 0 1' au lieu de deux)? – Pac0

Répondre

0

Pas grand-chose efficace, mais fait le travail (si je comprends bien le problème à droite):

myList.GroupBy(x=>x.field1) 
     .Where(g=>g.Count()>1) 
     .SelectMany(g=>g) 
     .GroupBy(x=>new{x.field1,x.field2}) 
     .Where(g=>g.Count()==1) 
     .SelectMany(g=>g); 

Pour un échantillon de quelques tuples ci-dessous:

var myList = new List<Tuple<int,int>>{ 
    new Tuple<int,int>(1,2), 
    new Tuple<int,int>(1,2), 
    new Tuple<int,int>(1,3), 
    new Tuple<int,int>(1,4), 
    new Tuple<int,int>(2,3), 
    new Tuple<int,int>(2,4), 
}; 

ce rendement (couru sur LINQPad) :

enter image description here

+0

Est-ce que votre 'where'clause juste se débarrasser de toutes les entrées qui sont dupliquées, au lieu de garder un de chaque (se débarrasser des seules entrées en double)? (Je ne sais pas si j'ai bien compris la requête de l'OP) – Pac0

+0

Je pense que OP a besoin de tous les doublons basés sur 'field1'; mais veut exclure ceux qui sont en double sur 'field2' aussi, (Je ne sais pas si j'ai bien compris.) – mshsayem

0

Je pencherais pour la création d'une coutume IEqualityComparer:

class MyClass { 
    public int field1; 
    public int field2; 
} 

class MyClassComparer: EqualityComparer<MyClass> 
{ 
    public override bool Equals(MyClass x, MyClass y) 
    { 
     if (x == null && y == null) 
      return true; 
     else if (x == null || x == null) 
      return false; 

     if (x.field1 == y.field1 && x.field2 == y.field2) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public override int GetHashCode(MyClass x) 
    { 
     int hCode = x.field1.GetHashCode()^x.field2.GetHashCode(); 
     return hCode.GetHashCode(); 
    } 
} 

Ensuite, vous pouvez simplement ajouter un

.Distinct(new MyClassComparer()) 

à la liste des résultats. somehting comme (peut-être besoin une certaine adaptation, ne peut pas le tester en ce moment):

dups = myList 
    .AsParallel() 
    .GroupBy(x => x.field1) 
    .Where(x => x.Count() > 1) 
    .Select(x => x.Key) 
    .ToList(); 

undupeds = 
    dups.Distinct(new MyClassComparer()); 

mise en garde: Cela ne se débarrasser des doublons après la requête db.

0
List<Fields> RemoveDuplicates(List<Fields> fields) 
    { 
     List<Fields> removedDuplicates = new List<Fields>(); 

     fields.ForEach(f => 
     { 
      if (removedDuplicates.FindAll(d => 
       d.Field1 == f.Field1 && 
       d.Field2 == f.Field2).Count == 0) 
      { 
       removedDuplicates.Add(f); 
      } 
     }); 

     return removedDuplicates; 
    } 

Vous ne savez pas si c'est exactement ce que vous demandez, mais il devrait créer une nouvelle liste qui n'a qu'une seule instance d'un objet "Champs" pour chaque copie dans la liste originale.