在修改数组时迭代数组是否安全?

时间:2019-04-19 15:47:14

标签: arrays swift iteration

我知道你不应该,我知道为什么。但是我的意思是,一旦我真正想知道发生了什么,就不会理解自己的代码。

所以我有一个带有一堆对象的数组。我正在对其进行迭代,一旦找到具有特定类型的对象,便将其从数组中删除,然后将另一个对象添加到数组中。像这样:

var arr = parent.allchildren() //getting all the children in array
for ele in arr{
   if(ele==somethingHere){
      parent.remove(ele)
      parent.add(new ele) //add new child into child array
   }
}

如果我有一个1,2,3,4,5的数组,并且在迭代时删除了3并添加了6,则实际数组将是1,2,4,5,6,但我正在迭代的数组仍然是1,2,3,4,5。

我认为这会很好,因为最后我仍然可以得到想要的东西,它删除了元素并添加了我需要的元素。但是在迭代时修改列表很不好,您不应该这样做,但是就我而言,我认为它可以满足我的需求。我看不到的潜在问题是什么?

2 个答案:

答案 0 :(得分:0)

我刚刚在操场上用以下代码进行了测试:

var arr = ["hi", "bye", "guy", "fry", "sky"]

for a in arr {
    if arr.count >= 3 {
        arr.remove(at: 2)
    }
    print(a)
}

print(arr)

此打印:

hi
bye
guy
fry
sky
["hi", "bye"]

因此,当您在Swift中使用for-in循环时,似乎会复制该数组,并且您对其进行的更改将不会影响您要遍历的数组。要回答您的问题,只要您了解这是行为,那么这样做就没有错。

答案 1 :(得分:0)

您可能要考虑做的一件事是在迭代结束时进行所有更改。不必一一进行更改,而是在迭代时记录要进行的更改,然后在循环完成后实际进行更改。

例如,您可以创建要删除的元素数组,并添加要添加的元素数组。

//Our array where we record what we want to add
var elementsToAdd = [Any]()

//Our array of what elements we want to remove. We record the index at 
//which we want to remove the element from the array
var indexesToRemoveAt = [Int]()

//Getting all the children in array
var arr = parent.allchildren()

//Enumerating an array allows us to access the index at which that 
//element occurs. For example, the first element's index would be 0, 
//the second element's index would be 1, the third would be 2, and so 
//on
for (index,ele) in arr.enumerated() {
  if(ele == somethingHere) {
    indexesToRemoveAt.append(index)
    elementsToAdd.append(newEle)
   }
 }

 //Now that we have recorded the changes we want to make, we could make 
 //all of the changes at once
 arr.remove(at: indexesToRemoveAt)
 arr.append(contentsOf: elementsToAdd)

请注意,删除多个索引处的数组元素将需要对Array进行以下扩展。如果要避免创建此扩展名,则可以始终循环遍历索引数组,并告诉该数组在每个单独的索引处删除。这些扩展功能实际上所做的就是遍历索引,并删除该索引处的数组元素。

数组扩展以删除多个索引处的元素:

extension Array {
  //Allows us to remove at multiple indexes instead of just one
  mutating func remove(at indexes: [Int]) {
    for index in indexes.sorted(by: >) {
      if index <= count-1 {
        remove(at: index)
      }
    }
  }
}