是否有可能在迭代时从mutablearray中删除字典?

时间:2014-08-11 08:03:56

标签: ios objective-c nsmutablearray nsdictionary

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];
    }  
}

假设optionDataArr包含一个没有值的字典,当上面的代码执行时我收到:

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

4 个答案:

答案 0 :(得分:4)

使用普通旧for循环时可以删除项目,使用快速枚举时不能删除。

但是你的代码很麻烦。删除第n个元素时,下一个元素将是(n + 2)th。您需要手动将索引递减1以考虑转移的元素。

还要记住,在这种情况下,你真的需要做&#34;实时&#34;在循环中检查数组长度的边界,而不仅仅是使用保持长度的临时变量(或者你也需要递减那个)。

答案 1 :(得分:3)

在这一行之下:

[optionDataArr removeObjectAtIndex:i];

添加以下行:

i--;

所以,代码是:

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

原因:在迭代数组时从数组中删除项目时,索引会发生更改。所以,这就是你需要手动减少索引的原因。

答案 2 :(得分:3)

Eiko的回答是正确的,但我想使用快速枚举显示其他版本。您无法使用快速枚举删除项目,因此您已存储索引,然后删除相应的项目:

NSMutableIndexSet * indexesToRemove = [NSMutableIndexSet indexSet];

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

[optionDataArr removeObjectsAtIndexes:indexesToRemove];

编辑:

当Martin R sugested时,您也可以使用indexesOfObjectsPassingTest方法:

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

答案 3 :(得分:1)

如果您进行了Eiko已经提到的修改,您当然可以使用标准for循环。

然而,在Objective C中处理此问题的惯用方法是迭代数组的副本:

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

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

虽然这确实需要数组的副本,除非您确定要处理大量数据,否则我将从可读版本开始,并在必要时优化到plain for循环。