Brejuro
Brejuro

Reputation: 3541

Adding element to an array while iterating over it

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?

Upvotes: 6

Views: 14503

Answers (4)

user8554794
user8554794

Reputation:

@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])

Upvotes: 1

Luke
Luke

Reputation: 848

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
    }
}

Upvotes: 0

ghostatron
ghostatron

Reputation: 2650

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.

Upvotes: 0

Kubba
Kubba

Reputation: 3438

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")
    }
}

Upvotes: 3

Related Questions