149 votes

Comment vérifier si un objet existe déjà dans une liste ?

J'ai une liste

  List<MyObject> myList

Je suis en train d'ajouter des éléments à une liste et je veux vérifier si cet objet est déjà dans la liste.

donc avant que je fasse ça :

 myList.Add(nextObject);

Je veux voir si nextObject est déjà dans la liste.

L'objet "MonObjet" possède un certain nombre de propriétés, mais la comparaison est basée sur la mise en correspondance de deux propriétés.

Quelle est la meilleure façon d'effectuer une vérification avant d'ajouter un nouveau "MyObject" à cette liste de "MyObject" ?

La seule solution à laquelle j'ai pensé est de passer d'une liste à un dictionnaire, puis de faire de la clé une chaîne concaténée des propriétés (ce qui semble un peu inélégant).

D'autres solutions plus propres utilisant des listes ou LINQ ou autre chose ?

195voto

Rex M Points 80372

Cela dépend des besoins de la situation spécifique. Par exemple, l'approche par dictionnaire serait tout à fait appropriée en supposant :

  1. La liste est relativement stable (pas beaucoup d'insertions/suppressions, ce pour quoi les dictionnaires ne sont pas optimisés).
  2. La liste est assez grande (sinon l'overhead du dictionnaire est inutile).

Si les éléments ci-dessus ne correspondent pas à votre situation, utilisez simplement la méthode Any() :

Item wonderIfItsPresent = ...
bool containsItem = myList.Any(item => item.UniqueProperty == wonderIfItsPresent.UniqueProperty);

Cette fonction énumérera la liste jusqu'à ce qu'elle trouve une correspondance, ou jusqu'à ce qu'elle atteigne la fin.

0 votes

L'utilisation d'un délégué prédicat pour le list.exists est une autre solution voir ci-dessous, mais si vous avez des listes énormes et valeur clé avec un dictionnaire sera beaucoup plus rapide car il est une table de hachage ! Bonne lecture

1 votes

Comment vérifier une valeur multiple ?

0 votes

Cette solution ne fonctionne que pour .NET 5.0+ . Malheureusement, certains d'entre nous ne disposent pas de cette version :-(

70voto

p.campbell Points 42771

S'il est possible de maintenir l'utilisation de ces deux propriétés, vous pouvez le faire :

bool alreadyExists = myList.Any(x=> x.Foo=="ooo" && x.Bar == "bat");

0 votes

Seulement à partir de .Net 5 +

10voto

Ani Points 59747

Êtes-vous sûr d'avoir besoin d'une liste dans ce cas ? Si vous remplissez la liste avec de nombreux éléments, les performances en souffriront. myList.Contains ou myList.Any ; le temps d'exécution sera quadratique. Vous pourriez envisager d'utiliser une meilleure structure de données. Par exemple,

 public class MyClass
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }

    }

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

            return x.Property1 == y.Property1 && x.Property2 == y.Property2;
        }

        public override int GetHashCode(MyClass obj)
        {
            return obj == null ? 0 : (obj.Property1.GetHashCode() ^ obj.Property2.GetHashCode());
        }
    }

Vous pouvez utiliser un HashSet de la manière suivante :

  var set = new HashSet<MyClass>(new MyClassComparer());
  foreach(var myClass in ...)
     set.Add(myClass);

Bien sûr, si cette définition de l'égalité pour MyClass est "universel", il n'est pas nécessaire d'écrire un fichier IEqualityComparer vous pouvez simplement remplacer GetHashCode et Equals dans la classe elle-même.

0 votes

Oui, bool pour V était mon préféré. D'ailleurs, il n'y a pas si longtemps (environ 3 semaines) que je n'avais pas accès à HashSet parce que je travaillais sur du code 2.0, et j'ai ajouté l'implémentation Mono de HashSet parce que c'est tellement utile :)

5voto

Un autre point à mentionner est que vous devez vous assurer que votre fonction d'égalité est conforme à vos attentes. Vous devez remplacer la méthode equals pour définir les propriétés de votre objet qui doivent correspondre pour que deux instances soient considérées comme égales.

Alors vous pouvez simplement faire mylist.contains(item)

3voto

Jon Hanna Points 40291

Edit : J'avais d'abord dit :


Qu'y a-t-il d'inélégant dans la solution du dictionnaire ? Elle me semble parfaitement élégante, d'autant plus qu'il suffit de définir le comparateur lors de la création du dictionnaire.


Bien entendu, il est inélégant d'utiliser un élément comme clé lorsqu'il est également la valeur.

J'utiliserais donc un HashSet. Si des opérations ultérieures nécessitaient une indexation, je créerais une liste à partir de celle-ci lorsque l'ajout serait terminé, sinon, j'utiliserais simplement le hashset.

0 votes

Je ne l'utiliserais que si la liste d'objets est énorme, car il s'agit d'une table de hachage et elle est idéale pour les recherches rapides.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X