数组遍历的同时删除元素

NSArray *tempArray = @[@"A",@"A",@"B",@"C",@"D",@"A"];
NSMutableArray *dataArray = [NSMutableArray arrayWithArray:tempArray];

正序遍历

方式一, 使用 for in遍历可变数组的同时删除元素会造成崩溃:
 for (NSString *obj in dataArray) {
        if ([obj isEqualToString:@"A"]) {
            [dataArray removeObject:obj];
        }
  }
方式二, 使用 enumerateObjectsUsingBlock 遍历可变数组的同时删除元素:
   [dataArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"obj ----- %@---index---%ld",obj,idx);
        if ([obj isEqualToString:@"A"]) {
            [dataArray removeObject:obj];
        }
    }];
方式三, 使用 for index 方式遍历可变数组同时删除元素:
 for (int i = 0; i < dataArray.count; i++) {
        NSString *obj = dataArray[i];
       NSLog(@"obj -----%@---index---%d",obj,i);
        if ([obj isEqualToString:@"A"]) {
            [dataArray removeObject:obj];
        }
    }

结论

从上面来看只for in会造成崩溃,其他方式对数组遍历,然后再删除元素就没有问题了。
但是如果删除元素,数组总长度会变化,如果内部再嵌套循环,那么就无法完全遍历

逆序遍历

方式一, 使用 for in遍历可变数组的同时删除元素仍会造成崩溃:(亲测)
 for (NSString *obj in dataArray.reverseObjectEnumerator) {
        if ([obj isEqualToString:@"A"]) {
            [dataArray removeObject:obj];
        }
    }
方式二, enumerateObjectsWithOptions:NSEnumerationReverse
 [dataArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"obj -----%@---index---%ld",obj,idx);
        if ([obj isEqualToString:@"A"]) {
            [dataArray removeObject:obj];
        }
    }];
obj -----A---index---5
obj -----A---index---4
obj -----A---index---3
obj -----D---index---2
obj -----C---index---1
obj -----B---index---0

结论

从上面来看只for in会造成崩溃,enumerateObjectsWithOptions对数组遍历会逆序循环6次,内部元素顺序会发生改变。

总结

1.如果是单循环,那么删除元素,removeObject 会将数组内部相同元素都删除。
2.如果是嵌套循环,那么删除元素,数组长度会发生改变,从而无法完全遍历,建议copy一个数组进行循环删减。也可以使用逆序遍历enumerateObjectsWithOptions:方式

你可能感兴趣的:(数组遍历的同时删除元素)