2010-05-07 6 views
1

J'ai entendu dire que c'est une mauvaise idée de faire quelque chose comme ça. Mais je suis sûr qu'il y a une règle empirique qui peut aider à obtenir ce droit.Manière sûre d'itérer sur un tableau ou un dictionnaire et de supprimer des entrées?

Lorsque je parcourt un NSMutableDictionary ou un NSMutableArray, je dois souvent me débarrasser des entrées. Cas typique: vous itérez dessus, et comparez l'entrée à quelque chose. Parfois, le résultat est «n'en a plus besoin» et vous devez l'enlever. Mais cela affecte l'index de toutes les lignes, n'est-ce pas?

Alors, comment pourrais-je parcourir en toute sécurité sans dépasser les limites accidentellement ou sauter par-dessus un élément qui n'a pas été vérifié?

Répondre

8

Vous le faites en créant un tableau temporaire ou un dictionnaire. Soit

  • (Dictionary) Ajoutez les clés que vous souhaitez supprimer ultérieurement au tableau temporaire ou
  • (Array) Ajouter les indices que vous souhaitez supprimer plus tard à un NSIndexSet ou
  • Ajoutez les objets que vous souhaitez garder au tableau temporaire ou dictionnaire

Ensuite, soit parcourir la TODELETE liste temporaire, la suppression de la liste principale (il pourrait y avoir des méthodes d'utilité pour cela), ou remplacer le dictonary/tableau existant avec votre "temporaire".

4

Si vous supprimez un objet d'un tableau modifiable pendant que vous enumerez le même tableau, l'application tombera en panne. Gardez une trace des objets que vous souhaitez supprimer (vous pouvez conserver leurs index dans un NSIndexSet) et utilisez la méthode -(void)removeObjectsAtIndexes:(NSIndexSet *)indexes une fois que vous êtes en dehors de la boucle d'énumération. Vous pouvez également conserver un NSArray des objets que vous êtes en train d'énumérer et utiliser -(void)removeObjectsInArray:(NSArray *)otherArray pour les supprimer une fois la boucle terminée.

Vérifiez les documents NSMutableArray pour obtenir des explications sur les méthodes.

http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html

1

Voici une façon intelligente de créer la copie, itérer et suppression:

for (id obj in [[myArray copy] autorelease]) { 
    BOOL condition = ... 
    if (condition) { 
     [myArray removeObject:obj]; 
    } 
} 

S'il est important que vous itérer dans le sens inverse pour une raison:

for (id obj in [[[myArray copy] autorelease] reverseObjectEnumerator]) { 
    BOOL condition = ... 
    if (condition) { 
     [myArray removeObject:obj]; 
    } 
} 
2

Ou vous pouvez toujours utiliser l'index explicite dans la boucle, puis le manipuler tout en supprimant des objets. Donc, il ressemblerait à quelque chose comme ça

for(unsigned int i = 0; i < [myArray count]; i++) { 
     id obj = [myArray objectAtIndex:i]; 
     if (condition) { 
      [myArray removeObject: obj]; 
      i--; 
     } 
} 
1

Étant donné que votre tableau ne contient pas d'éléments [NSNull null] (qui il sera très probablement pas de toute façon), vous pouvez simplement remplacer tous les éléments dont vous avez besoin d'avoir enlevé avec [NSNull null] lors de l'énumération et une fois l'énumération terminée, appelez simplement [array removeObjectIdenticalTo:[NSNull null]] ([NSNull null] est un hack singleton et framework pour permettre l'insertion de nil dans des tableaux). Cela peut être utile lorsque la mémoire est un problème et donc que les copies de tableau ne sont pas une option ou lorsque la matrice ne peut tout simplement pas être remplacée par une copie.