如何在枚举过程中删除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一个数组,然后遍历数组。 在这种情况下,不需要摆弄索引值。