Change value of array in for-loop

Hey there,

I have the following problem:
When I change the value of an array in a for-loop the array is not saved with this new value.

Example:

Code Block swift
var numbers = [2, 3, 4, 6, 9]
let theNumber = 4
print("Numbers old: \(numbers)")
for var number in numbers {
    if number == theNumber {
        print("Numbers are identical")
        number = 10
        /*save the changed number in array*/
    }
}
print("Numbers new: \(numbers)")


The console output is:

Numbers old: [2, 3, 4, 6, 9]
Numbers are identical
Numbers new: [2, 3, 4, 6, 9]

So the value of the array is not changed.
How to modify the code so that the value of the array is changed?
Is there an easy way to do so?

Help is very welcome!
Thank you!

Accepted Reply

So the value of the array is not changed.

Right. This is expected. When you use a var in a for loop like this, you can a read-write copy of the number value but it’s not bound to the original numbers array.

How to modify the code so that the value of the array is changed?

The easiest way to fix your code is to iterate over the indexes:

Code Block
for i in numbers.indices {
if numbers[i] == theNumber {
numbers[i] = 10
}
}


However, the best (IMO, obviously :-) way to fix it is to avoid the for loop entirely:

Code Block
let newNumbers = numbers.map { number in
number == theNumber ? 10 : number
}


Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"

Replies

Why do you expect array to be changed ?

You should replace number by the new value, like here:

Code Block
var pos = -1
for var number in numbers {
pos += 1
if number == theNumber {
print("Numbers are identical")
number = 10
numbers[pos] = number
/*save the changed number in array*/
}
}
print("Numbers new: \(numbers)")


You get:
Numbers are identical
Numbers new: [2, 3, 10, 6, 9]

So the value of the array is not changed.

Right. This is expected. When you use a var in a for loop like this, you can a read-write copy of the number value but it’s not bound to the original numbers array.

How to modify the code so that the value of the array is changed?

The easiest way to fix your code is to iterate over the indexes:

Code Block
for i in numbers.indices {
if numbers[i] == theNumber {
numbers[i] = 10
}
}


However, the best (IMO, obviously :-) way to fix it is to avoid the for loop entirely:

Code Block
let newNumbers = numbers.map { number in
number == theNumber ? 10 : number
}


Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Thank you!
You welcome.My post took just 11 hours for being reviewed ! This forum moderation is a bit bizarre.

Good continuation.
Hm, now I have a further question:
See this example:

Code Block swift
struct testClass {
    var One = ["test": "zzz", "test2": false] as [String : Any]
    var Two = ["test": "***", "test2": true] as [String : Any]
    
    var allOfThem: [[String:Any]]
    
    init() {
        allOfThem = [One, Two]
    }
}
var theTest = testClass()
for i in theTest.allOfThem.indices {
    print(theTest.allOfThem[i])
    if theTest.allOfThem[i]["test"] as? String == "zzz" {
        print("Test found")
        theTest.allOfThem[i]["test2"] = true
        print("Test data: \(theTest.allOfThem[i])")
    }
}
print("Test finally: \(theTest.One)")


Console's output is:


["test2": false, "test": "zzz"]

Test found

Test data: ["test2": true, "test": "zzz"

["test2": true, "test": "***"]

Test finally: ["test2": false, "test": "zzz"]

As you can see, if I set up true in the array it is false at the end.
If there are just one or two dictionaries in class this is not a huge problem. But if there are 10 it is nasty to use a switch statement to detect all of them. So I want to save the true in the var One also if I'm running trough the array. Any way to do this?
I think it’d help if you explained more of the bigger picture here. Your Swift is kinda strange and it’s hard to recommend the best approach without knowing more about the real problem.

For example, I would never do any of the following in Swift:
  • Name a type with a leading lower case letter

  • Name a property with a leading upper case letter

  • Name a struct with the suffix Class

  • Have arrays of Any, unless forced to by the system

  • Likewise for arrays of arrays of Any

  • Have code outside of a type do complex manipulations on that type’s internals

In contrast, I would do the following:
  • Use strong types to model my data

  • Use an enum instead of Any, so I can explicitly model the possible states

  • Use encapsulation to centralise my implementation of an algorithm, rather than merging arrays

  • Use built-in algorithms — like the map example I showed in my earlier response — rather than writing my own loops

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
Thanks for the advice!

Sorry for the strange code, I just tried to show you the problem using an example in a playground, so that I mustn't add my whole project here.

But I solved the problem now myself. So everything is fine.