遍历可变数组的同时删除元素

      很多时候遍历数组的同时需要删除数组里面符合条件的元素。那么哪种删除方法正确呢?错误的方法错在哪里?我觉得有必要分析一下。

方法一:for 循环,索引器i < [numberArray count]  for循环遍历,没有用到枚举遍历的。因此程序是不会崩溃的。

 NSMutableArray *numberArray = [[NSMutableArray alloc] init];
    for (int i  = 1; i < 6; i++) {
        NSNumber *nsnumber = [NSNumber numberWithInt:i];
        [numberArray addObject:nsnumber];
    }

    for (int i = 0; i < [numberArray count]; i++) {
        NSNumber *number = [numberArray objectAtIndex:i];
        if ([number intValue] == 3) {
             [numberArray removeObject:number];
            NSLog(@"删除的数为%@",number);
        }
        NSLog(@"%@",[numberArray objectAtIndex:i]);
    }
    
    NSLog(@"%@",numberArray);

输出结果为:1  、2、{删除的数为3、4}、5。     {1,2,4,5} 

虽然删除了 数组中元素值为3的元素 ,输出了5个元素,但是循环次数其实变为了4次。因为在删除3的for循环中i值为2,删除i后,数组元素前移,本来下标为3的4元素,变为下标为2的4元素。if语句结束后执行NSLOG语句输出下标为2的4元素。 i++ 值变为3,输出 5。

关于测试代码规范的重要性。

上面代码不规范因为有NSLOG小细节需要注意,没有注意的化会认为循环次数没有改变,因此上面的代码不是合格的测试代码。

下面的代码清晰的展示了删除后数组下标的变化和循环次数。

 for (int i = 0; i < [numberArray count]; i++) {
        NSNumber *number = [numberArray objectAtIndex:i];
        if ([number intValue] == 3) {
             [numberArray removeObject:number];
            NSLog(@"删除数时i的值为%d",i);
            NSLog(@"删除的数为%@",number);
            NSLog(@"删除后数组的长度为%ld",[numberArray count]);
            NSLog(@"/**********************/");
        } else
        {
        NSLog(@"当前i的值为%d",i);
        NSLog(@"当前数组的长度为%ld",[numberArray count]);
        NSLog(@"当前遍历的数为%@",[numberArray objectAtIndex:i]);
        NSLog(@"/**********************/");
        }
    }

输出结果:0 ,1;1,2;2,删除3;3,5。  可以看到 删除3 后,4前移下标变为2,5前移下标变为3。一共循环输出了4次,出现了4元素没有被输出情况。

若数组改变后仍要输出下标为4的元素就回报错,报错如下:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 4 beyond bounds [0 .. 3]'

意思是说下标为4的元素,已经越界了。

综上所述,因此在for循环的时候,可变数组numberArray长度已经发生改变,且被删除元素后面的元素会先前移动。这类似于链表的存储结构。

// 待续。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值