507 votes

Comment faire pour supprimer des éléments dans une liste générique tout en effectuant une itération sur elle ?

Je suis à la recherche d'un meilleur "modèle" pour travailler avec une liste des éléments qui ont chacun besoin traitées et ensuite, selon les résultats sont supprimés de la liste.

Vous ne pouvez pas utiliser .Remove(element) à l'intérieur d'un foreach (var element in X)... vous aussi vous ne pouvez pas utiliser for (int i = 0; i < elements.Count(); i++) et .RemoveAt(i).

Auparavant, j'ai fait des choses folles comme ceci (résumé = construction d'une structure générique autour de la "élément" de tenir une valeur vraie ou fausse qui détermine si oui ou non il doit être supprimé de la liste):

public List<String> AttemptToProcessList(List<string> list) {

    var listTracked = new List<KeyValuePair<string, bool>>();

    list.ForEach(item => listTracked.Add(new KeyValuePair<string, bool>(item, false)));

    for (int i = 0; i < listTracked.Count; i++) {

        var result = ProcessListItem(listTracked[i].Key);

        if (result) {
            listTracked[i] = new KeyValuePair<string, bool>(listTracked[i].Key, true);
        }
     }

     foreach (var item in listTracked.Where( listItem => listItem.Value )) {
         list.Remove(item.Key);
     }

     return list;
}

839voto

Ahmad Mageed Points 44495

Parcourir votre liste en sens inverse avec une boucle for :

Exemple :

Alternativement, vous pouvez utiliser la méthode RemoveAll avec un prédicat pour tester contre :

Voici un exemple simplifié de démontrer :

87voto

Jan Points 708

Une solution simple et intuitive :

Utilisez une boucle for standard en cours d’exécution en arrière sur votre collection et RemoveAt(i) pour supprimer les éléments.

75voto

UndercoverAgent Points 591

Itération inverse doit être la première chose à venir à l’esprit lorsque vous souhaitez supprimer des éléments d’une Collection tout en effectuant une itération sur elle.

Heureusement, il existe une solution plus élégante qu’écrire une boucle qui consiste à taper inutile et peut être source d’erreurs.

24voto

À l’aide de la ToArray() sur une liste générique permet d’effectuer un Remove(item) sur votre liste de générique :

24voto

JulianR Points 7257

Sélectionnez les éléments que vous ne voulez plutôt que d'essayer de supprimer les éléments que vous ne voulez. C'est tellement plus facile (et généralement plus efficace aussi) que la suppression des éléments.

var newSequence = (from el in list
                   where el.Something || el.AnotherThing < 0
                   select el);

Je voulais poster ce qu'un commentaire en réponse au commentaire laissé par Michael Dillon ci-dessous, mais c'est trop long et probablement utile d'avoir dans ma réponse de toute façon:

Personnellement, je n'avais jamais supprimer les éléments un par un, si vous avez besoin de retrait, puis appelez RemoveAll qui prend un prédicat et seulement réorganise le tableau interne une fois, alors qu' Remove un Array.Copy l'opération pour chaque élément que vous retirez. RemoveAll est beaucoup plus efficace.

Et quand vous êtes en arrière itérer sur une liste, vous avez déjà l'indice de l'élément que vous souhaitez supprimer, de sorte qu'il serait beaucoup plus efficace d'appeler RemoveAtcar Remove le premier un parcours de la liste pour rechercher l'index de l'élément que vous tentez de supprimer, mais vous savez déjà que l'indice.

Donc dans l'ensemble, je ne vois aucune raison de l'appeler Remove dans une boucle for. Et dans l'idéal, si c'est possible, utilisez le code ci-dessus pour diffuser des éléments de la liste comme nécessaire, donc pas de deuxième structure de données doit être créé à tous les.

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