我們想要刪除數(shù)組中的符合條件的元素時,經(jīng)常對數(shù)組進(jìn)行遍歷,然后刪除。但是這其中更確隱藏著很大的問題。如果當(dāng)初能夠仔細(xì)的分析一下,也不會導(dǎo)致今天的錯誤了。
比如我們有一個數(shù)組 CCArray *array;包含了value值分別為1~5的NSNumber對象,現(xiàn)在我們想刪除其中value為1和2的兩個對象,我們可能會這樣操作:
1.? for(NSNumber * number in array)
2.? {
3.? ? ? ? ? CCLOG(@"number:%@ ",[number description]);
4.? ? ? ? ? if([number intValue]==2||[number intValue]==1) {
5.? ? ? ? ? ? ? [array removeObject:number];
6.? ? ? ? ? ? ? CCLOG(@"delete:%@ ",[number description]);
7.? ? ? ? ? }
8.? ? }
但這樣操作,只會刪除value為1的對象。因為刪除這個對象后,array的count減少了,被刪掉的對象后面的元素會向前移動,這樣在這個for循環(huán)中就會漏掉1后面的那個對象,而且測試也發(fā)現(xiàn),雖然循環(huán)中間刪除了一個元素,但循環(huán)的次數(shù)并沒有減少,只不過最后兩次都是最后一個元素。
打印的值如下:
l? number:0
l? number:1
l? delete:1
l? number:3
l? number:4
l? number:4
如果我們使用如下的循環(huán)方式:
for (int i=0;i<[array count];i++) {
NSNumber *number = [array objectAtIndex:i];
CCLOG(@"number %d:%@ ",i,[number description]);
if ([number intValue]==2||[number intValue]==1) {
[array removeObject:number];
CCLOG(@"delete:%@ ",[number description]);
}
}
打印的值會變?yōu)椋?/p>
l? Number 0:0
l? Number 1:1
l? delete:1
l? number 2:3
l? number 3:4
可見同樣的問題,在刪除value為1的對象后,計數(shù)器增長為2,但此時數(shù)組中下標(biāo)為2的元素已經(jīng)變成了之前下標(biāo)為3的對象,因為刪除其中一個元素后,后面的所有元素都會向前移動,這個下標(biāo)都會改變。這樣變漏掉了一些元素。對于for in快速枚舉,還會多次執(zhí)行最后一個元素的遍歷,這些都是導(dǎo)致問題的隱患。
為了避免以上的問題,我們可以使用倒序的方式刪除:
int num = [array count];
for (int i=num-1;i>=0;i--) {
NSNumber *number = [array objectAtIndex:i];
CCLOG(@"number %d:%@ ",i,[number description]);
if ([number intValue]==2||[number intValue]==1) {
[array removeObjectAtIndex:i];
CCLOG(@"delete:%@ ",[number description]);
}
}
另外也可以通過創(chuàng)建臨時數(shù)組的方式來解決,將所有要保留的對象加入另外一個數(shù)組,并完全刪除原數(shù)組,或者將要刪除的元素加入臨時數(shù)組,然后執(zhí)行[CCArray removeObjectInArray:];