2

I'm trying to insert new key-value pair in dictionary, which nested in another one Dictionary:

var dict = Dictionary<Int, Dictionary<Int, String>>()

dict.updateValue([1 : "one", 2: "two"], forKey: 1)
dict[1]?[1] // {Some "one"}

if var insideDic =  dict[1] {
    // it is a copy, so I can't insert pair this way:
    insideDic[3] = "three"
}

dict // still [1: [1: "one", 2: "two"]]

dict[1]?[3] = "three" // Cannot assign to the result of this expression
dict[1]?.updateValue("three", forKey: 3) // Could not find a member "updateValue"

I believe should be a simple way to handle it, but I spent an hour and still can't figure it out. I can use NSDictionary instead, but I really like to understand how I should manage nested Dictionaries in Swift?

ColinE
  • 68,894
  • 15
  • 164
  • 232
Ilya Belikin
  • 645
  • 1
  • 5
  • 15
  • 3
    possible duplicate of [swift: modifying arrays inside dictionaries](http://stackoverflow.com/questions/24534229/swift-modifying-arrays-inside-dictionaries) – Nate Cook Jul 03 '14 at 13:42
  • Yes, it is essentially the same struggle. Sorry, I missed it at first time. Should I somehow link to it and close this one? – Ilya Belikin Jul 04 '14 at 00:38

1 Answers1

2

Dictionarys are value types so are copied on assignment. As a result you are going to have to get the inner dictionary (which will be a copy), add the new key, then re-assign.

// get the nested dictionary (which will be a copy)
var inner:Dictionary<Int, String> = dict[1]!

// add the new value
inner[3] = "three"

// update the outer dictionary
dict[1] = inner
println(dict) // [1: [1: one, 2: two, 3: three]]

You could use one of the new utility libraries such as ExSwift to make this a bit simpler:

dict[1] = dict[1]!.union([3:"three"])

This uses the union method that combines two dictionaries.

ColinE
  • 68,894
  • 15
  • 164
  • 232
  • 3
    Uurgh… Swift at its worst. We shouldn't be having to use utility libraries to do this. – Ashley Mills Jul 03 '14 at 13:47
  • 3
    True, the array and dictionary behaviour is causing a *lot* of confusion at the moment. – ColinE Jul 03 '14 at 13:50
  • Thank you, now it is clear. It takes cognitive shift to accept this answer... feels so counterintuitive. And I only hope compiler will optimize it to dust, because in my real case this dictionary is huge. – Ilya Belikin Jul 04 '14 at 00:44
  • Performance is the issue in current state of Swift, see [Swift's Dictionary is slow even with -Ofast](http://stackoverflow.com/questions/24476943/swifts-dictionary-is-slow-even-with-ofast?lq=1) – Ilya Belikin Jul 04 '14 at 01:19
  • 1
    @IlyaBelikin you could cheat to make it work - rather than storing dictionaries within dictionaries, Create a class which acts as a dictionary reference, and store this in your 'outer' dictionary instead! – ColinE Jul 04 '14 at 07:49
  • I don't think this is correct anymore; see e.g. [here](http://stackoverflow.com/a/41566988/539599). – Raphael Jan 10 '17 at 14:04