remove - C#- moyen le plus rapide de comparer une collection par rapport à elle-même pour trouver des doublons




distinct object list c# (4)

public class TestObject
{
    string TestValue { get; set; }
    bool IsDuplicate { get; set; }
}

List<TestObject> testList = new List<TestObject>
{
    new TestObject { TestValue = "Matt" },
    new TestObject { TestValue = "Bob" },
    new TestObject { TestValue = "Alice" },
    new TestObject { TestValue = "Matt" },
    new TestObject { TestValue = "Claire" },
    new TestObject { TestValue = "Matt" }
};

Imaginez que testList est en réalité des millions d'objets.

Quel est le moyen le plus rapide de s'assurer que deux de ces trois TestObjects avec TestValue de Matt obtiennent leur IsDuplicate à true? Peu importe comment les instances d'une valeur donnée sont, un seul devrait sortir du processus avec IsDuplicate de false.

Je ne suis pas opposé à faire cela via le filetage. Et la collection ne doit pas être une liste si la conversion vers un autre type de collection est plus rapide.

Je dois garder les doublons et les marquer comme tels, ne pas les retirer de la collection.

Pour développer, c'est (comme vous pouvez l'imaginer) une simple expression d'un problème beaucoup plus complexe. Les objets en question ont déjà un ordinal que je peux utiliser pour les ordonner.

Après avoir mis en correspondance les doublons initiaux sur l'égalité exacte des chaînes, je vais devoir revenir en arrière dans la collection et réessayer le reste en utilisant une logique de correspondance approximative. La collection qui existe au début de ce processus ne sera pas modifiée pendant la déduplication ou après.

Finalement, la collection d'origine va être écrite dans un fichier, avec probablement des doublons signalés.


Depuis que vous avez indiqué que vous avez une propriété qui conserve l'ordinal de vos articles. Nous pouvons utiliser cette propriété pour réinitialiser l'ordre de tri à son original après avoir marqué nos éléments en tant que doublons.

Le code ci-dessous est auto-explicatif. Mais laissez-moi savoir au cas où vous auriez besoin d'explications supplémentaires.

J'ai supposé que le nom de la propriété est SortOrder . Modifiez le code en conséquence.

void MarkDuplicates()
{
    testList = testList.OrderBy(f => f.TestValue).ThenBy(f => f.SortOrder).ToList();
    for (int i = 1; i < testList.Count; i++) 
    {
        if (testList[i].TestValue == testList[i - 1].TestValue) testList[i].IsDuplicate = true;
    }
    testList = testList.OrderBy(f => f.SortOrder).ToList();
}

Je ne suis pas un expert en performance. Mais vous pouvez chronométrer les différentes solutions fournies ici et vérifier la performance par vous-même.


J'irais probablement vérifier les doublons en construisant la collection de TestValue pour éviter de faire deux boucles sur des millions d'éléments. Si ce scénario est possible, j'utiliserais un Dictionary<string, List<TestValue>>

Dictionary<string, List<TestValue>> myList = new Dictionary<string, List<TestValue>>();
while(NotEndOfData())
{
     TestValue obj = GetTestValue();
     if(myList.ContainsKey(obj.Name))
     {
         obj.IsDuplicate = true;
         myList[obj.Name].Add(obj);
     }
     else
     {
         obj.IsDuplicate = false;
         myList.Add(obj.Name, new List<TestValue>() { obj};
     }
}

C'est probablement très performant:

foreach (var dupe in testList.GroupBy(x => x.TestValue).SelectMany(g => g.Skip(1)))
    dupe.IsDuplicate = true;

[EDIT] Cette méthode s'avère être environ un tiers de la vitesse de la réponse acceptée ci-dessus, de sorte que l'on devrait être utilisé. Cette réponse est simplement d'intérêt académique.


Comme d'autres l'ont mentionné, l'approche correcte ici serait d'utiliser la classe HashSet.

var hashSet = new HashSet<string>();

foreach (var obj in testList)
{
    if (!hashSet.Add(obj.TestValue))
    {
        obj.IsDuplicate = true;
    }
}

Lorsque vous ajoutez une valeur à HashSet pour la première fois, elle s'ajoute avec succès et la méthode HashSet.Add() renvoie true, donc vous n'apportez aucune modification à l'élément. Lorsque vous essayez de l'ajouter une deuxième fois, HashSet.Add() renvoie false et vous marquez votre élément en tant que doublon.

La liste aura l'état suivant après l'exécution de notre méthode de marquage en double:

Matt
Bob
Alice
Claire
Matt DUPLICATE




duplicates