如何在枚举过程中删除NSMutableArray或NSMutableDictionary中的元素?

我正在使用基于块的枚举类似于下面的代码:

[[[rows objectForKey:self.company.coaTypeCode] objectForKey:statementType] enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id coaItem, NSUInteger idx, BOOL *stop) { // block code here }] 

我想在枚举过程中删除一些对象取决于它们的对象值。

我怎么能这样做? 我知道在枚举过程中操作可变数组或字典(NSMutableArray或NSMutableDictionary)通常是不可能的。

什么是实施这个最好的方法?

谢谢!

由于枚举过程中无法从数组或字典中删除对象,因此必须累积要删除的项目,然后在枚举后将其全部删除。

如果你正在处理一个数组,你可以累积指数:

 NSMutableIndexSet *indexesToDelete = [NSMutableIndexSet indexSet]; NSUInteger currentIndex = 0; for (id obj in yourArray) { //do stuff with obj if (shouldBeDeleted(obj)) { [indexesToDelete addIndex:currentIndex]; } currentIndex++; } [yourArray removeObjectsAtIndexes:indexesToDelete]; 

由于NSDictionary中键的顺序是未定义的,因此对于NSMutableDictionary,您将不得不累积键:

 NSMutableArray *keysToDelete = [NSMutableArray array]; for (id obj in [yourDictionary keyEnumerator]) { //do stuff with obj if (shouldBeDeleted(obj)) { [keysToDelete addObject:obj]; } } [yourDictionary removeObjectsForKeys:keysToDelete]; 

如果你用一个块来枚举,那也是一样的。 将枚举数声明在声明块的相同范围内,它将被保留并且正常工作。

也是值得从3年前看这个问题: 在迭代时从NSMutableArray中移除的最佳方法? 。

无论是在枚举过程中build立一个索引集,还是在枚举过程中修改数组本身,都必须放弃NSEnumerationConcurrent ,因为大多数Cocoa对象不能同时从多个线程安全地同时修改。

无论如何,最简单(但也许不是最有效)的方法是枚举容器的副本。

对于数组,您可以枚举相反的副本。 我假设,当每个项目被列举,你可能会决定删除该项目,但不是其他项目以前列举或尚未枚举。

 NSMutableArray *array = [[rows objectForKey:self.company.coaTypeCode] objectForKey:statementType]; [[array copy] enumerateObjectsWithOptions: NSEnumerationReverse usingBlock:^(id coaItem, NSUInteger idx, BOOL *stop) { if ([self objectIsTooUglyToExist:coaItem]) [array removeObjectAtIndex:idx]; }] 

您必须反向枚举数组,以避免更改数组中尚未枚举的部分。

对于字典,你可以枚举没有特殊选项的副本:

 NSMutableDictionary *dictionary = someDictionary; [[dictionary copy] enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { if ([self object:obj isTooUglyToExistAtKey:key]) [dictionary removeObjectForKey:key]; }]; 

另外一个select是使用一个常规的for循环,数组的count作为限制。 然后需要认识到是否从一个位置<=索引(在这种情况下索引应该递减)或>索引(在这种情况下,除了for语句的增量以外,索引保持不变) 。

对于字典,您可以先用allKeys创build一个数组,然后遍历数组。 在这种情况下,不需要摆弄索引值。