2

I have been trying to run this loop to change the position of an element in an array based but I get the error below. Not really sure what could be wrong. Any thoughts or Ideas!! Thanks.

enter image description here

var population = [[98, 8, 45, 34, 56], [9, 13, 65, 4, 90], [24, 5, 4, 56, 88], [3, 55, 22, 19, 10]]

private func randomIntergerInRange(low:Int, high:Int) -> Int {
    let randomGeneratedNumber = low + Int(arc4random()) % (high - low);
    return Int(randomGeneratedNumber)
}

for individual in population {
    var mutate = 0.01

    if mutate > Double(Float(arc4random()) / Float(UINT32_MAX)) {

        var positionToMutate = randomIntergerInRange(0, (individual.count - 1))

        var valueToAssign = randomIntergerInRange(minElement(individual), maxElement(individual))

        individual[positionToMutate] = valueToAssign
        print(individual)

    }
}
2
  • why your array look more like an Dictionary Commented Aug 30, 2015 at 16:17
  • It's an array of Arrays @Lamar ;) Commented Aug 30, 2015 at 16:20

2 Answers 2

2

Array are passed by value, so when you use individual at each iteration it is assigned a copy of the subarray of population, and even if you use for var individual in population ... you mutate only a copy of the original array.

If you want to mutate the values of the original array you can do it by using indices, for instance:

for index in population.indices {
    var mutate = 0.01

    if mutate > Double(Float(arc4random()) / Float(UINT32_MAX)) {

        var positionToMutate = randomIntergerInRange(0, (population[index].count - 1))

        var valueToAssign = randomIntergerInRange(minElement(population[index]), maxElement(population[index]))

        population[index][positionToMutate] = valueToAssign
        print(population[index])

    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Oh I see. I wasn't aware of that. Thanks a lot. ;) @Renzo
1

Reason for the error message: the individual object in your loop is immutable, it's a copy of the object, not a reference.

You could do something like this, using enumerate:

for (index, individual) in enumerate(population) {
    var mutate = 0.01

    if mutate > Double(Float(arc4random()) / Float(UINT32_MAX)) {

        var positionToMutate = randomIntergerInRange(0, (individual.count - 1))

        var valueToAssign = randomIntergerInRange(minElement(individual), maxElement(individual))

        population[index][positionToMutate] = valueToAssign

        print(population[index])

    }
}

You shouldn't modify a collection while iterating it, btw, it could have side effects.

Update for Swift 2

private func randomIntegerInRange(low:Int, _ high:Int) -> Int {
    let randomGeneratedNumber = low + Int(arc4random()) % (high - low)
    return Int(randomGeneratedNumber)
}

var mutate = 0.01
for (index, individual) in population.enumerate() {
    if mutate > Double(Float(arc4random()) / Float(UINT32_MAX)) {
        var positionToMutate = randomIntegerInRange(0, (individual.count - 1))
        if let min = individual.minElement(), max = individual.maxElement() {
            var valueToAssign = randomIntegerInRange(min, max)
            population[index][positionToMutate] = valueToAssign
            print(population[index])
        }
    }
}

1 Comment

Thanks. ;). Stuff I wasn't really sure of!.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.