NSMutableArray遍历删除元素

6 篇文章 0 订阅

在学习Objective-C的过程中,我们会学到NSMutableArray这个类,也就是可变数组。在做和可变数组相关的编程题的时候,我们会遇到一个这样的问题:在对数组遍历时删除数组元素。
有些人一看,很简单嘛,forin 遍历就解决了,我们来看一下用forin解决这个问题的结果
我们先假设一个场景,一个数组中存了n个联系人,现在我们要根据姓名删除联系人
[objc] view plaincopy
for (AddressPerson *perName in array) {
if ([[perName name] isEqualToString:@”Zhangsan”]) {
[array removeObject:perName];
}
}

这是用forin遍历来解决这个问题的代码实现,当我们运行程序时,程序crash了,这是为什么啊?逻辑是哪个没有错误啊,语法也没有报错啊?我们来看一下程序crash的原因

红色框中是crash原因,意思是当数组被枚举时被修改了,因为forin遍历时规定不能修改数组元素。但是,这里有一个特殊点,假如你想要删除的是数组中最后一个元素的话,程序就不会crash了。这是因为当到最后一个元素时,已经遍历结束了,forin的工作算是结束了,你再删除数组元素已经和它没有关系了,就不会发生冲突了。
那我们应该怎么解决这个问题呢?下面我们来看几种解决方案
方案一:既然forin遍历会crash,那么我们就采用for循环遍历,我们来看一下代码:
[objc] view plaincopy
for (int i = 0; i < [array count]; i++) {
AddressPerson *perName = [array objectAtIndex:i];
if ([[perName name] isEqualToString:@”Zhangsan”]) {
[array removeObject:perName];
NSLog(@”删除成功”);
}
}

这种算法是遍历整个数组,找到元素的姓名和想要删除的联系人匹配的数组元素,然后删除,用for循环遍历时可以对数组进行修改,所以这种方法是可行的.
有些人说就想用forin遍历怎么办?那么我们来看其他解决方案
方案二: 定义一个副本,遍历副本找到想要删除的元素,然后在原数组中删除对应的元素.代码实现如下:
[objc] view plaincopy
NSMutableArray *copyArray = [NSMutableArray arrayWithArray:array];
char name[20] = {0}; // 存储姓名
NSLog(@”请输入想要删除的联系人的姓名:”);
scanf(“%s”, name);
NSString *str1 = [NSString stringWithUTF8String:name];
for (AddressPerson *perName in copyArray) {
if ([[perName name] isEqualToString:str1]) {
[array removeObject:perName];
}
}

这种算法的思想就是.对副本数组遍历,对原数组进行相应操作.
方案三:对数组逆序遍历,查找对应元素后删除
[objc] view plaincopy
// 逆序遍历,然后查找删除
NSEnumerator *enumerator = [array reverseObjectEnumerator];
//forin遍历
for (AddressPerson *groupName in enumerator) {
if ([[groupName group] isEqualToString:@”Zhangsan”]) {
[array removeObject:groupName];
}
}

这种算法的思想是:我们从数组元素最后一个开始查找,如果找到匹配的,就删除
有些人会有疑问,你这也是遍历数组时对数组进行改变不了啊,为什么逆序就可以啊?
具体情况是这样的,当我们正序遍历时,如果删除了一个,那么没有遍历到的元素位置都会往前移动一位,这样系统就无法确定接下来遍历是从删除位置开始呢,还是从删除位置下一位开始呢?这样就造成程序crash了.对于逆序遍历就不会,因为我们逆序遍历时,遇到匹配的元素删除后,位置改变的是遍历过得元素,而没有遍历到的元素位置却没有改变,所以遍历能够正常进行.
关于这个问题的解决方案暂时就这么多,如果大家觉得我写的哪种解决方案有问题,还望多多指教.如果你有更好的解决方案,希望我们能多多交流.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值