0

I have created a dictionary like this

var MyArray: [String:[String:[Int]]] = [
    "xx": ["x1": [1, 2, 3], "x2": [4, 5, 6], "x3": [7, 8, 9]],
    "yy": ["y1": [10, 11, 12], "y2": [13, 14, 15], "y3": [16, 17, 18]]]

How can I change the value 3 in "x1" in "xx" to an other number? I don't know that this is the number 3 but i know that it is in MyArray["xx"]!["x1"]![2]

Alex Karapanos
  • 895
  • 2
  • 7
  • 20

2 Answers2

1
// example setup
var myArray: [String:[String:[Int]]] = [
    "xx": ["x1": [1, 2, 3], "x2": [4, 5, 6], "x3": [7, 8, 9]],
    "yy": ["y1": [10, 11, 12], "y2": [13, 14, 15], "y3": [16, 17, 18]]]

// value to be replaced
let oldNum = 3

// value to replace old value by
let newNum = 4

// extract the current value (array) for inner key 'x1' (if it exists),
// and proceed if 'oldNum' is an element of this array
if var innerArr = myArray["xx"]?["x1"], let idx = innerArr.index(of: oldNum) {
    // replace the 'oldNum' element with your new value in the copy of
    // the inner array
    innerArr[idx] = newNum

    // replace the inner array with the new mutated array
    myArray["xx"]?["x1"] = innerArr
}

print(myArray)
/* ["yy": ["y3": [16, 17, 18], "y2": [13, 14, 15], "y1": [10, 11, 12]],
    "xx": ["x1": [1, 2, 4], "x3": [7, 8, 9], "x2": [4, 5, 6]]]
                        ^ ok! */

Based on the following Q&A:

A more performant approach would be actually removing the inner array (for key "x1"); mutating it; and re-adding it to the dictionary

// check if 'oldNum' is a member of the inner array, and if it is: remove
// the array and mutate it's 'oldNum' member to a new value, prior to
// adding the array again to the dictionary
if let idx = myArray["xx"]?["x1"]?.index(of: oldNum), 
    var innerArr = myArray["xx"]?.removeValue(forKey: "x1") {
    innerArr[idx] = newNum
    myArray["xx"]?["x1"] = innerArr
}

print(myArray)
// ["yy": ["y3": [16, 17, 18], "y2": [13, 14, 15], "y1": [10, 11, 12]], "xx": ["x1": [1, 2, 4], "x3": [7, 8, 9], "x2": [4, 5, 6]]]
Community
  • 1
  • 1
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • This could benefit from some description. Code-only answers are frowned upon. Explain why this code needs/should be used. – rmaddy Dec 18 '16 at 21:44
  • @rmaddy I was in the progress of editing it with code comment descriptions (which are now included, 30 seconds after your comment), but thanks for the (very swift) reminder :) – dfrib Dec 18 '16 at 21:45
  • @dfri I am trying to replace the '3' with a variable of an Int var `Currentindex = 3` and it show me the following error: `Cannot invoke 'indexOf' with an argument list of type'(of: Int)'`, but why? – Alex Karapanos Dec 18 '16 at 21:59
  • @sunbile You should update your question showing your code and error. – rmaddy Dec 18 '16 at 22:00
  • @sunbile are you using Swift 3? (`indexOf` is a deprecated syntax from Swift < 3). I updated the answer to using a property (`oldNum`) rather than a literal. – dfrib Dec 18 '16 at 22:02
  • @dfri Yes 3.0, does that mean that i can't use a variable instead of the number directly? – Alex Karapanos Dec 18 '16 at 22:06
  • @sunbile If you are using 3.0, then the above should work as it is. I was just curious that the error message you mention contains `indexOf`, which is the old name of the `index(of:)` method of `Array`. Are you sure you are using exactly the same approach as above, and that you are using Swift 3.0? (and not e.g. Swift 2.3 legacy support) – dfrib Dec 18 '16 at 22:07
  • @dfri Sorry, my mistake the error is: `Cannot invoke 'index' with an argument list of type'(of: Int)'`. Yes, I'm using Swift 3.0 and it doesn't work. – Alex Karapanos Dec 18 '16 at 22:12
  • @sunbile I can't help you out without more details, as this works perfectly fine for me (hinting that you are indeed not fully following the answer and pre-conditions above). I encourage you to test the fully functional example in my answer above to see if your error still persists. If it does not, try to modify the example into your own code, and you will likely stumble upon what you are doing wrong (and different from the example above). (Taking a guess, it would seem that the inner array is not `[Int]`; is it possibly in fact `[Any]`? E.g. from a JSON response, and not created as in your Q) – dfrib Dec 18 '16 at 22:14
0

If you know the index of the number you would like to change out of the three, you can change the number 3 directly using the subscripts ["xx"]?["x1"]?[2].

var myArray = [
    "xx": [
        "x1": [1, 2, 3],
        "x2": [4, 5, 6],
        "x3": [7, 8, 9]
    ],
    "yy": [
        "y1": [10, 11, 12],
        "y2": [13, 14, 15],
        "y3": [16, 17, 18]
    ]
]

array["xx"]?["x1"]?[2] = 4
Callam
  • 11,409
  • 2
  • 34
  • 32