How to update nested dictionary in swift [duplicate]How to update a value in a nested dictionary given path fragment in Swift?How to merge two dictionaries in a single expression?How do I efficiently iterate over each entry in a Java Map?How do I sort a list of dictionaries by a value of the dictionary?What is the best way to iterate over a dictionary?How do I sort a dictionary by value?Add new keys to a dictionary?Check if a given key already exists in a dictionaryIterating over dictionaries using 'for' loopsDelete an element from a dictionaryHow to remove a key from a Python dictionary?
Personal Teleportation as a Weapon
Is a roofing delivery truck likely to crack my driveway slab?
Is there a problem with hiding "forgot password" until it's needed?
How does residential electricity work?
What are the ramifications of creating a homebrew world without an Astral Plane?
Everything Bob says is false. How does he get people to trust him?
Tiptoe or tiphoof? Adjusting words to better fit fantasy races
What's a natural way to say that someone works somewhere (for a job)?
Cynical novel that describes an America ruled by the media, arms manufacturers, and ethnic figureheads
Where in the Bible does the greeting ("Dominus Vobiscum") used at Mass come from?
If you attempt to grapple an opponent that you are hidden from, do they roll at disadvantage?
Is it okay / does it make sense for another player to join a running game of Munchkin?
Was Spock the First Vulcan in Starfleet?
I'm in charge of equipment buying but no one's ever happy with what I choose. How to fix this?
How was Earth single-handedly capable of creating 3 of the 4 gods of chaos?
Print name if parameter passed to function
Is the destination of a commercial flight important for the pilot?
Was the picture area of a CRT a parallelogram (instead of a true rectangle)?
Why is delta-v is the most useful quantity for planning space travel?
Efficiently merge handle parallel feature branches in SFDX
Coordinate position not precise
Using parameter substitution on a Bash array
How do I rename a LINUX host without needing to reboot for the rename to take effect?
Hostile work environment after whistle-blowing on coworker and our boss. What do I do?
How to update nested dictionary in swift [duplicate]
How to update a value in a nested dictionary given path fragment in Swift?How to merge two dictionaries in a single expression?How do I efficiently iterate over each entry in a Java Map?How do I sort a list of dictionaries by a value of the dictionary?What is the best way to iterate over a dictionary?How do I sort a dictionary by value?Add new keys to a dictionary?Check if a given key already exists in a dictionaryIterating over dictionaries using 'for' loopsDelete an element from a dictionaryHow to remove a key from a Python dictionary?
This question already has an answer here:
How to update a value in a nested dictionary given path fragment in Swift?
2 answers
I have nested dictionary, so something like this:
var dict = ["a":["b":"c", "d":["e":"f"]], "f":["b":"g"]] // and more
Now if I want to update the value of key a.d.e, how should I do that?
It seems updateValue method only reads key as it is...It doesn't know anything about the nested key.
Edit:
While I really want to change the structure of this data to something easier to work with. I can't. This belongs to another class and I am not allow to change the structure, all I can do is to update it.
Second Edit:
After some thoughts and read the other question some one point out might be a duplicate, tried recursively updating. I feel this is seriously the worst way to do it because essentially it's creating new dictionaries with a copy of original value and assign it back. I do think it is a waste of space and tbh even recursively calling this I feel is unnecessary.
func updateKey(key:[AnyHashable],val:Bool,data:[AnyHashable:Any])->[AnyHashable:Any]
var keyTemp = key
var tempData = data
if(keyTemp.count==1)
tempData.updateValue(val, forKey: key[0])
print(tempData)
return tempData
else
var firstLayerValue = data[keyTemp[0]] as? [AnyHashable:Any]
var firstKey = keyTemp.removeFirst()
var tempResult = updateKey(key: keyTemp, val: val, data: firstLayerValue!)
tempData.updateValue(tempResult, forKey: firstKey)
return tempData;
This returns a copy of what I intend to do, and I have to actually assign it back to the original copy. I really don't like this assigning back and forth thing, what if something went wrong in the middle then I might just end up losing the originally correct data.
Is there any better solution?
swift dictionary
marked as duplicate by Dávid Pásztor, matt
StackExchange.ready(function()
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();
);
);
);
Mar 21 at 15:58
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
|
show 4 more comments
This question already has an answer here:
How to update a value in a nested dictionary given path fragment in Swift?
2 answers
I have nested dictionary, so something like this:
var dict = ["a":["b":"c", "d":["e":"f"]], "f":["b":"g"]] // and more
Now if I want to update the value of key a.d.e, how should I do that?
It seems updateValue method only reads key as it is...It doesn't know anything about the nested key.
Edit:
While I really want to change the structure of this data to something easier to work with. I can't. This belongs to another class and I am not allow to change the structure, all I can do is to update it.
Second Edit:
After some thoughts and read the other question some one point out might be a duplicate, tried recursively updating. I feel this is seriously the worst way to do it because essentially it's creating new dictionaries with a copy of original value and assign it back. I do think it is a waste of space and tbh even recursively calling this I feel is unnecessary.
func updateKey(key:[AnyHashable],val:Bool,data:[AnyHashable:Any])->[AnyHashable:Any]
var keyTemp = key
var tempData = data
if(keyTemp.count==1)
tempData.updateValue(val, forKey: key[0])
print(tempData)
return tempData
else
var firstLayerValue = data[keyTemp[0]] as? [AnyHashable:Any]
var firstKey = keyTemp.removeFirst()
var tempResult = updateKey(key: keyTemp, val: val, data: firstLayerValue!)
tempData.updateValue(tempResult, forKey: firstKey)
return tempData;
This returns a copy of what I intend to do, and I have to actually assign it back to the original copy. I really don't like this assigning back and forth thing, what if something went wrong in the middle then I might just end up losing the originally correct data.
Is there any better solution?
swift dictionary
marked as duplicate by Dávid Pásztor, matt
StackExchange.ready(function()
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();
);
);
);
Mar 21 at 15:58
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
2
While this is possible, you should strongly avoid this kind of data structure in Swift. It is very awkward to work with. If at all possible, convert this to a struct, which will make this (and many other headaches) go away. There are ways to implement highly dynamic data structures if you have specialized use cases, but complex dictionaries (and especially a dictionary that includesAny
anywhere) are generally not the right tool. What does your data look like? I believe we can find a better data structure.
– Rob Napier
Mar 21 at 15:31
1
@Anna Ouch. I've been there before. Is the structure of the dict always going to be exactly the same every single time? You could create an enum for the various values you need to update, then have a method that takes the enum case as a parameter and just write a switch to handle the various values to update.
– Adrian
Mar 21 at 15:41
3
Wow…they've given you a really bad thing… Are the keys and values always strings? Or can the final value types be arbitrary? I have some ideas on how to attack it, but attacking the most general case is hard.
– Rob Napier
Mar 21 at 15:46
2
gfycat.com/impossiblesilentaxolotl
– Adrian
Mar 21 at 15:53
2
OK; I need to think about this. It's an…interesting problem. (And by that I mean an annoying problem you shouldn't have to face.)
– Rob Napier
Mar 21 at 15:54
|
show 4 more comments
This question already has an answer here:
How to update a value in a nested dictionary given path fragment in Swift?
2 answers
I have nested dictionary, so something like this:
var dict = ["a":["b":"c", "d":["e":"f"]], "f":["b":"g"]] // and more
Now if I want to update the value of key a.d.e, how should I do that?
It seems updateValue method only reads key as it is...It doesn't know anything about the nested key.
Edit:
While I really want to change the structure of this data to something easier to work with. I can't. This belongs to another class and I am not allow to change the structure, all I can do is to update it.
Second Edit:
After some thoughts and read the other question some one point out might be a duplicate, tried recursively updating. I feel this is seriously the worst way to do it because essentially it's creating new dictionaries with a copy of original value and assign it back. I do think it is a waste of space and tbh even recursively calling this I feel is unnecessary.
func updateKey(key:[AnyHashable],val:Bool,data:[AnyHashable:Any])->[AnyHashable:Any]
var keyTemp = key
var tempData = data
if(keyTemp.count==1)
tempData.updateValue(val, forKey: key[0])
print(tempData)
return tempData
else
var firstLayerValue = data[keyTemp[0]] as? [AnyHashable:Any]
var firstKey = keyTemp.removeFirst()
var tempResult = updateKey(key: keyTemp, val: val, data: firstLayerValue!)
tempData.updateValue(tempResult, forKey: firstKey)
return tempData;
This returns a copy of what I intend to do, and I have to actually assign it back to the original copy. I really don't like this assigning back and forth thing, what if something went wrong in the middle then I might just end up losing the originally correct data.
Is there any better solution?
swift dictionary
This question already has an answer here:
How to update a value in a nested dictionary given path fragment in Swift?
2 answers
I have nested dictionary, so something like this:
var dict = ["a":["b":"c", "d":["e":"f"]], "f":["b":"g"]] // and more
Now if I want to update the value of key a.d.e, how should I do that?
It seems updateValue method only reads key as it is...It doesn't know anything about the nested key.
Edit:
While I really want to change the structure of this data to something easier to work with. I can't. This belongs to another class and I am not allow to change the structure, all I can do is to update it.
Second Edit:
After some thoughts and read the other question some one point out might be a duplicate, tried recursively updating. I feel this is seriously the worst way to do it because essentially it's creating new dictionaries with a copy of original value and assign it back. I do think it is a waste of space and tbh even recursively calling this I feel is unnecessary.
func updateKey(key:[AnyHashable],val:Bool,data:[AnyHashable:Any])->[AnyHashable:Any]
var keyTemp = key
var tempData = data
if(keyTemp.count==1)
tempData.updateValue(val, forKey: key[0])
print(tempData)
return tempData
else
var firstLayerValue = data[keyTemp[0]] as? [AnyHashable:Any]
var firstKey = keyTemp.removeFirst()
var tempResult = updateKey(key: keyTemp, val: val, data: firstLayerValue!)
tempData.updateValue(tempResult, forKey: firstKey)
return tempData;
This returns a copy of what I intend to do, and I have to actually assign it back to the original copy. I really don't like this assigning back and forth thing, what if something went wrong in the middle then I might just end up losing the originally correct data.
Is there any better solution?
This question already has an answer here:
How to update a value in a nested dictionary given path fragment in Swift?
2 answers
swift dictionary
swift dictionary
edited Mar 21 at 18:15
Anna
asked Mar 21 at 15:27
AnnaAnna
136213
136213
marked as duplicate by Dávid Pásztor, matt
StackExchange.ready(function()
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();
);
);
);
Mar 21 at 15:58
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
marked as duplicate by Dávid Pásztor, matt
StackExchange.ready(function()
if (StackExchange.options.isMobile) return;
$('.dupe-hammer-message-hover:not(.hover-bound)').each(function()
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');
$hover.hover(
function()
$hover.showInfoMessage('',
messageElement: $msg.clone().show(),
transient: false,
position: my: 'bottom left', at: 'top center', offsetTop: -7 ,
dismissable: false,
relativeToBody: true
);
,
function()
StackExchange.helpers.removeMessages();
);
);
);
Mar 21 at 15:58
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
2
While this is possible, you should strongly avoid this kind of data structure in Swift. It is very awkward to work with. If at all possible, convert this to a struct, which will make this (and many other headaches) go away. There are ways to implement highly dynamic data structures if you have specialized use cases, but complex dictionaries (and especially a dictionary that includesAny
anywhere) are generally not the right tool. What does your data look like? I believe we can find a better data structure.
– Rob Napier
Mar 21 at 15:31
1
@Anna Ouch. I've been there before. Is the structure of the dict always going to be exactly the same every single time? You could create an enum for the various values you need to update, then have a method that takes the enum case as a parameter and just write a switch to handle the various values to update.
– Adrian
Mar 21 at 15:41
3
Wow…they've given you a really bad thing… Are the keys and values always strings? Or can the final value types be arbitrary? I have some ideas on how to attack it, but attacking the most general case is hard.
– Rob Napier
Mar 21 at 15:46
2
gfycat.com/impossiblesilentaxolotl
– Adrian
Mar 21 at 15:53
2
OK; I need to think about this. It's an…interesting problem. (And by that I mean an annoying problem you shouldn't have to face.)
– Rob Napier
Mar 21 at 15:54
|
show 4 more comments
2
While this is possible, you should strongly avoid this kind of data structure in Swift. It is very awkward to work with. If at all possible, convert this to a struct, which will make this (and many other headaches) go away. There are ways to implement highly dynamic data structures if you have specialized use cases, but complex dictionaries (and especially a dictionary that includesAny
anywhere) are generally not the right tool. What does your data look like? I believe we can find a better data structure.
– Rob Napier
Mar 21 at 15:31
1
@Anna Ouch. I've been there before. Is the structure of the dict always going to be exactly the same every single time? You could create an enum for the various values you need to update, then have a method that takes the enum case as a parameter and just write a switch to handle the various values to update.
– Adrian
Mar 21 at 15:41
3
Wow…they've given you a really bad thing… Are the keys and values always strings? Or can the final value types be arbitrary? I have some ideas on how to attack it, but attacking the most general case is hard.
– Rob Napier
Mar 21 at 15:46
2
gfycat.com/impossiblesilentaxolotl
– Adrian
Mar 21 at 15:53
2
OK; I need to think about this. It's an…interesting problem. (And by that I mean an annoying problem you shouldn't have to face.)
– Rob Napier
Mar 21 at 15:54
2
2
While this is possible, you should strongly avoid this kind of data structure in Swift. It is very awkward to work with. If at all possible, convert this to a struct, which will make this (and many other headaches) go away. There are ways to implement highly dynamic data structures if you have specialized use cases, but complex dictionaries (and especially a dictionary that includes
Any
anywhere) are generally not the right tool. What does your data look like? I believe we can find a better data structure.– Rob Napier
Mar 21 at 15:31
While this is possible, you should strongly avoid this kind of data structure in Swift. It is very awkward to work with. If at all possible, convert this to a struct, which will make this (and many other headaches) go away. There are ways to implement highly dynamic data structures if you have specialized use cases, but complex dictionaries (and especially a dictionary that includes
Any
anywhere) are generally not the right tool. What does your data look like? I believe we can find a better data structure.– Rob Napier
Mar 21 at 15:31
1
1
@Anna Ouch. I've been there before. Is the structure of the dict always going to be exactly the same every single time? You could create an enum for the various values you need to update, then have a method that takes the enum case as a parameter and just write a switch to handle the various values to update.
– Adrian
Mar 21 at 15:41
@Anna Ouch. I've been there before. Is the structure of the dict always going to be exactly the same every single time? You could create an enum for the various values you need to update, then have a method that takes the enum case as a parameter and just write a switch to handle the various values to update.
– Adrian
Mar 21 at 15:41
3
3
Wow…they've given you a really bad thing… Are the keys and values always strings? Or can the final value types be arbitrary? I have some ideas on how to attack it, but attacking the most general case is hard.
– Rob Napier
Mar 21 at 15:46
Wow…they've given you a really bad thing… Are the keys and values always strings? Or can the final value types be arbitrary? I have some ideas on how to attack it, but attacking the most general case is hard.
– Rob Napier
Mar 21 at 15:46
2
2
gfycat.com/impossiblesilentaxolotl
– Adrian
Mar 21 at 15:53
gfycat.com/impossiblesilentaxolotl
– Adrian
Mar 21 at 15:53
2
2
OK; I need to think about this. It's an…interesting problem. (And by that I mean an annoying problem you shouldn't have to face.)
– Rob Napier
Mar 21 at 15:54
OK; I need to think about this. It's an…interesting problem. (And by that I mean an annoying problem you shouldn't have to face.)
– Rob Napier
Mar 21 at 15:54
|
show 4 more comments
2 Answers
2
active
oldest
votes
Another way of doing it
dict["a"]?["d"] = ["e": 123]
print(dict)
Outputs
["f": ["b": "g"], "a": ["b": "c", "d": ["e": 123]]]
The OP mentioned in the comments that the type of the dictionary is[AnyHashable:Any]
– ielyamani
Mar 21 at 23:09
add a comment |
Structs are the way to go. But if you really have to use dictionaries, here is a workaround:
var dict: [AnyHashable: Any] =
["a": ["b": "c", "d": ["e":"f"]],
"f": ["b": "g"]]
let newValue = true
if var firstLevel = dict["a"] as? [String : Any],
var secondLevel = firstLevel["d"] as? [String: Any]
secondLevel["e"] = newValue
firstLevel["d"] = secondLevel
dict["a"] = firstLevel
print(dict) //[AnyHashable("a"): ["d": ["e": true], "b": "c"], AnyHashable("f"): ["b": "g"]]
To update a value in a dictionary with multiple levels, you can define a function like so:
func update(dictionary dict: inout [AnyHashable: Any], at keys: [AnyHashable], with value: Any)
if keys.count < 2
for key in keys dict[key] = value
return
var levels: [[AnyHashable: Any]] = []
for key in keys.dropLast()
if let lastLevel = levels.last
if let currentLevel = lastLevel[key] as? [AnyHashable: Any]
levels.append(currentLevel)
else if lastLevel[key] != nil, levels.count + 1 != keys.count
break
else return
else
if let firstLevel = dict[keys[0]] as? [AnyHashable : Any]
levels.append(firstLevel )
else return
if levels[levels.indices.last!][keys.last!] != nil
levels[levels.indices.last!][keys.last!] = value
else return
for index in levels.indices.dropLast().reversed()
levels[index][keys[index + 1]] = levels[index + 1]
dict[keys[0]] = levels[0]
And use it like so:
var dict: [AnyHashable: Any] = ["a": ["b": 1,
"c": ["d": ["e": "f"],
"g": ["h": 1.5]]],
"j": ["k": 2]]
update(dictionary: &dict,
at: ["a", "c", "d", "e"],
with: true)
dict.forEach print($0)
Here is the output in the console:
(key: AnyHashable("a"), value: [AnyHashable("b"): 1, AnyHashable("c"): [AnyHashable("d"): [AnyHashable("e"): true], AnyHashable("g"): ["h": 1.5]]])
(key: AnyHashable("j"), value: ["k": 2])
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Another way of doing it
dict["a"]?["d"] = ["e": 123]
print(dict)
Outputs
["f": ["b": "g"], "a": ["b": "c", "d": ["e": 123]]]
The OP mentioned in the comments that the type of the dictionary is[AnyHashable:Any]
– ielyamani
Mar 21 at 23:09
add a comment |
Another way of doing it
dict["a"]?["d"] = ["e": 123]
print(dict)
Outputs
["f": ["b": "g"], "a": ["b": "c", "d": ["e": 123]]]
The OP mentioned in the comments that the type of the dictionary is[AnyHashable:Any]
– ielyamani
Mar 21 at 23:09
add a comment |
Another way of doing it
dict["a"]?["d"] = ["e": 123]
print(dict)
Outputs
["f": ["b": "g"], "a": ["b": "c", "d": ["e": 123]]]
Another way of doing it
dict["a"]?["d"] = ["e": 123]
print(dict)
Outputs
["f": ["b": "g"], "a": ["b": "c", "d": ["e": 123]]]
answered Mar 21 at 15:52
Joakim DanielsonJoakim Danielson
10.2k3725
10.2k3725
The OP mentioned in the comments that the type of the dictionary is[AnyHashable:Any]
– ielyamani
Mar 21 at 23:09
add a comment |
The OP mentioned in the comments that the type of the dictionary is[AnyHashable:Any]
– ielyamani
Mar 21 at 23:09
The OP mentioned in the comments that the type of the dictionary is
[AnyHashable:Any]
– ielyamani
Mar 21 at 23:09
The OP mentioned in the comments that the type of the dictionary is
[AnyHashable:Any]
– ielyamani
Mar 21 at 23:09
add a comment |
Structs are the way to go. But if you really have to use dictionaries, here is a workaround:
var dict: [AnyHashable: Any] =
["a": ["b": "c", "d": ["e":"f"]],
"f": ["b": "g"]]
let newValue = true
if var firstLevel = dict["a"] as? [String : Any],
var secondLevel = firstLevel["d"] as? [String: Any]
secondLevel["e"] = newValue
firstLevel["d"] = secondLevel
dict["a"] = firstLevel
print(dict) //[AnyHashable("a"): ["d": ["e": true], "b": "c"], AnyHashable("f"): ["b": "g"]]
To update a value in a dictionary with multiple levels, you can define a function like so:
func update(dictionary dict: inout [AnyHashable: Any], at keys: [AnyHashable], with value: Any)
if keys.count < 2
for key in keys dict[key] = value
return
var levels: [[AnyHashable: Any]] = []
for key in keys.dropLast()
if let lastLevel = levels.last
if let currentLevel = lastLevel[key] as? [AnyHashable: Any]
levels.append(currentLevel)
else if lastLevel[key] != nil, levels.count + 1 != keys.count
break
else return
else
if let firstLevel = dict[keys[0]] as? [AnyHashable : Any]
levels.append(firstLevel )
else return
if levels[levels.indices.last!][keys.last!] != nil
levels[levels.indices.last!][keys.last!] = value
else return
for index in levels.indices.dropLast().reversed()
levels[index][keys[index + 1]] = levels[index + 1]
dict[keys[0]] = levels[0]
And use it like so:
var dict: [AnyHashable: Any] = ["a": ["b": 1,
"c": ["d": ["e": "f"],
"g": ["h": 1.5]]],
"j": ["k": 2]]
update(dictionary: &dict,
at: ["a", "c", "d", "e"],
with: true)
dict.forEach print($0)
Here is the output in the console:
(key: AnyHashable("a"), value: [AnyHashable("b"): 1, AnyHashable("c"): [AnyHashable("d"): [AnyHashable("e"): true], AnyHashable("g"): ["h": 1.5]]])
(key: AnyHashable("j"), value: ["k": 2])
add a comment |
Structs are the way to go. But if you really have to use dictionaries, here is a workaround:
var dict: [AnyHashable: Any] =
["a": ["b": "c", "d": ["e":"f"]],
"f": ["b": "g"]]
let newValue = true
if var firstLevel = dict["a"] as? [String : Any],
var secondLevel = firstLevel["d"] as? [String: Any]
secondLevel["e"] = newValue
firstLevel["d"] = secondLevel
dict["a"] = firstLevel
print(dict) //[AnyHashable("a"): ["d": ["e": true], "b": "c"], AnyHashable("f"): ["b": "g"]]
To update a value in a dictionary with multiple levels, you can define a function like so:
func update(dictionary dict: inout [AnyHashable: Any], at keys: [AnyHashable], with value: Any)
if keys.count < 2
for key in keys dict[key] = value
return
var levels: [[AnyHashable: Any]] = []
for key in keys.dropLast()
if let lastLevel = levels.last
if let currentLevel = lastLevel[key] as? [AnyHashable: Any]
levels.append(currentLevel)
else if lastLevel[key] != nil, levels.count + 1 != keys.count
break
else return
else
if let firstLevel = dict[keys[0]] as? [AnyHashable : Any]
levels.append(firstLevel )
else return
if levels[levels.indices.last!][keys.last!] != nil
levels[levels.indices.last!][keys.last!] = value
else return
for index in levels.indices.dropLast().reversed()
levels[index][keys[index + 1]] = levels[index + 1]
dict[keys[0]] = levels[0]
And use it like so:
var dict: [AnyHashable: Any] = ["a": ["b": 1,
"c": ["d": ["e": "f"],
"g": ["h": 1.5]]],
"j": ["k": 2]]
update(dictionary: &dict,
at: ["a", "c", "d", "e"],
with: true)
dict.forEach print($0)
Here is the output in the console:
(key: AnyHashable("a"), value: [AnyHashable("b"): 1, AnyHashable("c"): [AnyHashable("d"): [AnyHashable("e"): true], AnyHashable("g"): ["h": 1.5]]])
(key: AnyHashable("j"), value: ["k": 2])
add a comment |
Structs are the way to go. But if you really have to use dictionaries, here is a workaround:
var dict: [AnyHashable: Any] =
["a": ["b": "c", "d": ["e":"f"]],
"f": ["b": "g"]]
let newValue = true
if var firstLevel = dict["a"] as? [String : Any],
var secondLevel = firstLevel["d"] as? [String: Any]
secondLevel["e"] = newValue
firstLevel["d"] = secondLevel
dict["a"] = firstLevel
print(dict) //[AnyHashable("a"): ["d": ["e": true], "b": "c"], AnyHashable("f"): ["b": "g"]]
To update a value in a dictionary with multiple levels, you can define a function like so:
func update(dictionary dict: inout [AnyHashable: Any], at keys: [AnyHashable], with value: Any)
if keys.count < 2
for key in keys dict[key] = value
return
var levels: [[AnyHashable: Any]] = []
for key in keys.dropLast()
if let lastLevel = levels.last
if let currentLevel = lastLevel[key] as? [AnyHashable: Any]
levels.append(currentLevel)
else if lastLevel[key] != nil, levels.count + 1 != keys.count
break
else return
else
if let firstLevel = dict[keys[0]] as? [AnyHashable : Any]
levels.append(firstLevel )
else return
if levels[levels.indices.last!][keys.last!] != nil
levels[levels.indices.last!][keys.last!] = value
else return
for index in levels.indices.dropLast().reversed()
levels[index][keys[index + 1]] = levels[index + 1]
dict[keys[0]] = levels[0]
And use it like so:
var dict: [AnyHashable: Any] = ["a": ["b": 1,
"c": ["d": ["e": "f"],
"g": ["h": 1.5]]],
"j": ["k": 2]]
update(dictionary: &dict,
at: ["a", "c", "d", "e"],
with: true)
dict.forEach print($0)
Here is the output in the console:
(key: AnyHashable("a"), value: [AnyHashable("b"): 1, AnyHashable("c"): [AnyHashable("d"): [AnyHashable("e"): true], AnyHashable("g"): ["h": 1.5]]])
(key: AnyHashable("j"), value: ["k": 2])
Structs are the way to go. But if you really have to use dictionaries, here is a workaround:
var dict: [AnyHashable: Any] =
["a": ["b": "c", "d": ["e":"f"]],
"f": ["b": "g"]]
let newValue = true
if var firstLevel = dict["a"] as? [String : Any],
var secondLevel = firstLevel["d"] as? [String: Any]
secondLevel["e"] = newValue
firstLevel["d"] = secondLevel
dict["a"] = firstLevel
print(dict) //[AnyHashable("a"): ["d": ["e": true], "b": "c"], AnyHashable("f"): ["b": "g"]]
To update a value in a dictionary with multiple levels, you can define a function like so:
func update(dictionary dict: inout [AnyHashable: Any], at keys: [AnyHashable], with value: Any)
if keys.count < 2
for key in keys dict[key] = value
return
var levels: [[AnyHashable: Any]] = []
for key in keys.dropLast()
if let lastLevel = levels.last
if let currentLevel = lastLevel[key] as? [AnyHashable: Any]
levels.append(currentLevel)
else if lastLevel[key] != nil, levels.count + 1 != keys.count
break
else return
else
if let firstLevel = dict[keys[0]] as? [AnyHashable : Any]
levels.append(firstLevel )
else return
if levels[levels.indices.last!][keys.last!] != nil
levels[levels.indices.last!][keys.last!] = value
else return
for index in levels.indices.dropLast().reversed()
levels[index][keys[index + 1]] = levels[index + 1]
dict[keys[0]] = levels[0]
And use it like so:
var dict: [AnyHashable: Any] = ["a": ["b": 1,
"c": ["d": ["e": "f"],
"g": ["h": 1.5]]],
"j": ["k": 2]]
update(dictionary: &dict,
at: ["a", "c", "d", "e"],
with: true)
dict.forEach print($0)
Here is the output in the console:
(key: AnyHashable("a"), value: [AnyHashable("b"): 1, AnyHashable("c"): [AnyHashable("d"): [AnyHashable("e"): true], AnyHashable("g"): ["h": 1.5]]])
(key: AnyHashable("j"), value: ["k": 2])
edited Mar 21 at 23:05
answered Mar 21 at 15:50
ielyamaniielyamani
8,33462761
8,33462761
add a comment |
add a comment |
2
While this is possible, you should strongly avoid this kind of data structure in Swift. It is very awkward to work with. If at all possible, convert this to a struct, which will make this (and many other headaches) go away. There are ways to implement highly dynamic data structures if you have specialized use cases, but complex dictionaries (and especially a dictionary that includes
Any
anywhere) are generally not the right tool. What does your data look like? I believe we can find a better data structure.– Rob Napier
Mar 21 at 15:31
1
@Anna Ouch. I've been there before. Is the structure of the dict always going to be exactly the same every single time? You could create an enum for the various values you need to update, then have a method that takes the enum case as a parameter and just write a switch to handle the various values to update.
– Adrian
Mar 21 at 15:41
3
Wow…they've given you a really bad thing… Are the keys and values always strings? Or can the final value types be arbitrary? I have some ideas on how to attack it, but attacking the most general case is hard.
– Rob Napier
Mar 21 at 15:46
2
gfycat.com/impossiblesilentaxolotl
– Adrian
Mar 21 at 15:53
2
OK; I need to think about this. It's an…interesting problem. (And by that I mean an annoying problem you shouldn't have to face.)
– Rob Napier
Mar 21 at 15:54