6

I have a for loop that loops over each element in an array. Under a certain condition, I add another element to that array inside the loop. However, the loop doesn't take that new element into account. If there are 6 items originally in the array and while looping through, I add 2 more, it still only loops 6 times. How can I fix this?

for ingredient in ingredientList {
    if ingredient.name == "banana" {
        var orange = Ingredient(name: "orange")
        ingredientList.append(orange)
    }
    if ingredient.name == "orange" {
        // this never executes
    }
}

If one of my ingredients is a banana, add an orange to the list. However, the loop never even considers the newly added element. How can I accomplish something like this and why doesn't it work?

Brejuro
  • 3,421
  • 8
  • 34
  • 61

4 Answers4

4

try this:

var array = ["a", "b"]

for i in array.startIndex...array.endIndex {
    if array[i] == "b" {
        array.append("c")
        print("add c")
    }
    if array[i] == "c"{
        array.append("d")
        print("add d")
    }
}
Kubba
  • 3,390
  • 19
  • 34
  • This answer is very bad. See https://stackoverflow.com/a/44823937/1779477 for better solutions. – idmean Apr 23 '19 at 20:37
1

@ghostatron A collection’s indices property can hold a strong reference to the collection itself, causing the collection to be non-uniquely referenced. If you mutate the collection while iterating over its indices, a strong reference can cause an unexpected copy of the collection. To avoid the unexpected copy, use the index(after:) method starting with startIndex to produce indices instead.

var c = MyFancyCollection([10, 20, 30, 40, 50])
var i = c.startIndex
while i != c.endIndex {
    c[i] /= 5
    i = c.index(after: i)
}
 // c == MyFancyCollection([2, 4, 6, 8, 10])
0

I think there are two issues here:

  1. Generally speaking, you shouldn't modify a collection while enumerating it. At best, it will ignore you. In most languages it will just crash.

  2. I suspect what you are seeing here, is that your loop is working with a copy of the collection, but your "append" is modifying the original. My reasoning there is that in Swift, structs are typically copies rather than references, and freakishly enough...arrays and dictionaries are structs.

ghostatron
  • 2,620
  • 23
  • 27
0

You need to use a for loop instead of a for each loop and adjust the counter accordingly when adding an element

Int cntVar = 0

for x as Integer = 0 to ingredientList.count - 1 {
    if ingredientList(x + cntVar).name == "banana" {
        var orange = Ingredient(name: "orange")
        ingredientList.append(orange)
        x = x - 1
        cntVar = cntVar + 1
    }
    if ingredientList(x + cntVar).name == "orange" {
        //add needed function here
    }
}
Luke
  • 838
  • 7
  • 17