Is it possible to delete dictionary from mutablearray while iterating? [duplicate]

大兔子大兔子 提交于 2019-12-25 03:29:11

问题


for (int i = 0; i< [optionDataArr count]; i++) {
    NSString *sName  = [[optionDataArr objectAtIndex:i] objectForKey:kOptionName];
    NSString *sPrice = [[optionDataArr objectAtIndex:i] objectForKey:kOptionExtraPrice];

    if (sName.length == 0  && sPrice.length == 0) {
          [optionDataArr removeObjectAtIndex:i];
    }  
}

Suppose optionDataArr contains a dictionary having no values and when above code executes i receive:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

回答1:


You can remove items when using a plain old for loop, you cannot when using fast enumeration.

Your code is buggy, though. When you delete the nth element, the next element will be (n+2)th. You need to manually decrement the index by one to account for the shifted elements.

Also keep in mind, that in this case you really need to do "real time" bounds checking of the array length in the loop, and not just use a temporary variable holding the length (or you need to decrement that one as well).




回答2:


Below this line:

[optionDataArr removeObjectAtIndex:i];

add this line:

i--;

So, the code would be:

if (sName.length == 0  && sPrice.length == 0) {
    [optionDataArr removeObjectAtIndex:i];
    i--;
}

Reason: When you remove an item from an array while you are iterating on it, the indexes get changed. So, that's why you would need to manually decrement index.




回答3:


Eiko answer is correct, but i wanted to show an other version using fast enumeration. You cannot remove items using fast enumeration, so you have do store the indexes and then remove the corresponding items later :

NSMutableIndexSet * indexesToRemove = [NSMutableIndexSet indexSet];

[optionDataArr enumerateObjectsUsingBlock:^(NSDictionary *dico, NSUInteger idx, BOOL *stop) {
    if ([dico count] == 0)
        [indexesToRemove addIndex:idx];
}];

[optionDataArr removeObjectsAtIndexes:indexesToRemove];

EDIT :

As Martin R sugested, you can also use indexesOfObjectsPassingTestmethod :

NSIndexSet * indexesToRemove = [optionDataArr indexesOfObjectsPassingTest:^BOOL(NSDictionary *dico, NSUInteger idx, BOOL *stop) {
    return ([dico count] == 0);
}];
[optionDataArr removeObjectsAtIndexes:indexesToRemove];



回答4:


You can certainly use a standard for loop for this, provided you make the modifications that Eiko has already mentioned.

However, the idomatic way to handle this in Objective C is to iterate over a copy of the array:

for (id obj in [optionDataArr copy]) {
    // some processing code

    if (condition) {
        [optionDataArr removeObject:obj]
    }
}

While this does require a copy of the array, unless you know for sure that you are dealing with a significant amount of data, I would start with the readable version and optimise to the plain for loop when and if necessary.



来源:https://stackoverflow.com/questions/25238436/is-it-possible-to-delete-dictionary-from-mutablearray-while-iterating

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!