IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Comment parcourrir une collection ?


Sujet :

C#

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 29
    Par défaut Comment parcourrir une collection ?
    Bonjour,
    J'ai ceci qui fonctionne mais le remove me fait sortir de l'itterateur alors qu'il reste des elements à supprimer

    Code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    foreach (XElement result in doc.XPathSelectElements(patern)){
        sortBoucle = false; 
        result.Remove();
    }
    J'ai pensé parcourrir ma collection comme suit mais je n'ai pas encore les notions sur les Enumeration donc ce n'est pas correcte.

    Code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    IEnumerable<XElement>  elements = doc.XPathSelectElements(patern);
    for (int i = 0; i < elements.Count() ;i++ ) {
        // Je veux memoriser cet element
        el = (XElement) elements<i>;  
        //puis je veux ici l'effacer
       elements<i>.Remove();
    }
    // elements<i> est incorrect, [i] aussi, que faut il mettre?
    Merci d'avance

  2. #2
    Rédacteur

    Avatar de Jérôme Lambert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2003
    Messages
    4 451
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 451
    Par défaut
    Deux fautes dans ton code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    IEnumerable<XElement>  elements = doc.XPathSelectElements(patern);
    for (int i = 0; i < elements.Count() ;i++ ) {
        // Je veux memoriser cet element
        el = (XElement) elements<i>;  
        //puis je veux ici l'effacer
       elements<i>.Remove();
    }
    C'est element[i] avec des crochets.

    Et après un remove, il faut décrémenter le compteur pour ne pas rater l'élément suivant dans ton ienumerable.

    Ensuite, je sais pas si tu as cherché à savoir pourquoi il ne t'es pas possible de faire un remove dans un foreach. Je te donne quand même l'explication : lorsque tu utilises un foreach, un énumérateur est récupéré à partir de ta collection pour énumérer chaque élément. Si tu retires un élément de la collection originale, ton énumérateur se retrouve dans un état invalide.

  3. #3
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 251
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 251
    Par défaut
    si tu veux parcourir une collection pour en supprimer les éléments, il faut la parcourir en sens inverse, du dernier au premier élément car chaque suppression va réorganiser ta collection et va "perdre" la boucle qui est en train de la parcourir.

  4. #4
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 29
    Par défaut
    Oui je comprend ton eclairage.
    En revanche , je ne vois pas comment inverser le sens avec l'iterrateur foreach.
    Reste donc ma question comment ontenir l'element de rang i dans doc.XPathSelectElements(patern) que je parcour dans une boucle for i ...

    J'aimerai bien savoir juste cela même si j'ai finalement pu trouver une parade en bouclant mon iterration autant de fois qu'elle contient d'elements
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int u = elements.Count();
        while (u>0){
            u --;
            foreach (XElement result in doc.XPathSelectElements(patern)){
                result.Remove();
            }
       }

  5. #5
    Modérateur

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Avril 2007
    Messages
    1 996
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 996
    Par défaut
    Attention quand même aux "remove" sur un objet sur lequel tu es en train d'itérer...
    Pour ma part, je préfère créer un second objet. Et c'est cet objet que je manipule tant que j'itère.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    TonType tonObjet = doc.XPathSelectElements(patern);
    TonType tonObjetAIterer = tonObjet;
    foreach (XElement result in tonObjet){
        sortBoucle = false; 
        tonObjetAIterer.Remove();
    }
    tonObjet = tonObjetAIterer;

  6. #6
    Membre émérite Avatar de ppphil
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    617
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2007
    Messages : 617
    Par défaut
    Remove dans un foreach : Streng verboten comme on dit en chinois de Madrid...
    Pourquoi tu ne le fais pas tout simplement dans un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (i = longeur de la collection; i >=0; i--)
    ??

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    Il est vivement déconseillé de manipuler un objet énumérable pendant qu'on l'énumère donc...

    Ainsi, il n'est pas possible de supprimer les éléments d'une collection, si tu les énumère, car effectivement le fait de supprimer, modifie complètement l'énumérateur que tu utilise... ce qui va à l'encontre de la mécanique de fonctionnement des itérateurs.
    Même en C++ avec les itérateurs en lecture/écriture tu ne peux pas faire un foreach et donc une itération ascentionnelle pour supprimer des éléments...

    La meilleur solution, même si elle n'est pas gratuite en temps et en mémoire, est de faire la sélection de ce que tu veux garder.
    Pour cela plusieurs façon de procéder, soit tu utilise Linq to Object, et l'écriture avec une clause from, et tout particulièrement where pour filtrer ta sélection, soit tu utilise une méthode d'extension quelconque, convenant aux énumérations, qui permettent de faire un filtrage par le biais d'un prédicat (délégué, que tu va typiquement écrire en expression lamba ou méthode anonyme)
    Le résultat de ce filtrage va ensuite remplacer les éléments de ta collection.

    L'intérêt de cette méthode est quelle est particulièrement lisible et n'altère pas un itérateur quelconque.
    Sinon tu peux utiliser un for/do while/while mais attention il doit se faire dans le sens décroissant, donc de la fin vers le début, et surtout il est INDISPENSABLE d'utiliser un RemoveAt (ou équivalence) si la collection en dispose d'un qu'un Remove sur l'objet lui même, car les collections utilise la méthode Find avec un prédicat par défaut, en partant depuis le début de la collection pour trouver l'élément à supprimer qui match avec ce que tu as fourni.
    Seules les Dictionary/Hashtable et naturellement toutes les collections avec un couple clé/valeur, ne souffre pas de cet inconvénient et détail de profil, et permette donc de faire une sélection sur la clé... si tu travail directement sur la valeur, le problème reste le même.

Discussions similaires

  1. [C#] Comment créer une collection ?
    Par Dan971 dans le forum C#
    Réponses: 9
    Dernier message: 08/10/2006, 16h13
  2. Comment créer une collection d'objet ?
    Par ced600 dans le forum VBScript
    Réponses: 3
    Dernier message: 11/09/2006, 10h48
  3. [C#]Comment trier une collection?
    Par Cube55 dans le forum Windows Forms
    Réponses: 6
    Dernier message: 06/06/2006, 19h18
  4. Réponses: 7
    Dernier message: 10/05/2006, 11h15
  5. Comment créér une collection sous Delphi
    Par PsyKroPack dans le forum Langage
    Réponses: 6
    Dernier message: 11/02/2003, 13h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo