Write to Nested Dictionary (Swift 4) - swift

I have declared a dictionary in Swift as so: var dict = [String: [String: [String]]]().
What I am trying to do now is to write to the nested dictionary. I have used both codes below, however, none of them work as the initial key does not exist:
dict["Test"]?["One"] = ["Failed"]
dict["Test"]!["One"] = ["Failed"]
What I am trying to do is to create a key for ["One"], much like how you can create a key for a normal dictionary using dict[key].

You need to instantiate every inner dictionary.
var dict = [String : [String : [String]]]()
dict["Test"] = [String : [String]]()
dict["Test"]?["One"] = ["Worked"]
print(dict)
Make sure to avoid force unwrapping.

dict is empty. There is no value for the "Test" key.
One option is to provide a default:
dict["Test", default: [:]]["One"] = ["A", "B"]
You can take this one step further:
dict["Test2", default: [:]]["Two", default: []].append("Hello")
That last line will work for any combination of the keys "Test2" and "Two" existing or not before that is used.

Related

Swift 3: Dict from only one object in struct in array

I have a struct that looks like:
struct nameStruct {
let name: String
let index: Int
}
I have an NSMutableArray that contains about 50 objects of this struct
Right now, I fill the contents of my namesDict with
let namesDict:[String: Any] = ["names" : namesArray]
However, because I only need the index object for sorting, I'd like to only add the name attribute to the dictionary, something like this:
let namesDict:[String: Any] = ["names" : namesArray.name]
or, because of swift's nature:
let namesDict:[String: Any] = ["names" : (namesArray as! [nameStruct]).name]
(focus on the .name part which obviously doesn't work in Swift)
Right now, my best guess would be to create a new array in a loop, only adding the name of the contents of my namesArray - but if there was a way to do this in one line without another array "in between", this would be really nice.
You can use map.
let namesDict: [String: Any] = ["names": namesArray.map({ ($0 as! nameStruct).name })]

Append values to [String : AnyObject] or [String : String]

I want to append values to a variable of type [String : AnyObject] how do I do that? cause I can't do the ff.
var someObject:[String : AnyObject] = ["name":"John Diggle", "location":"Star City Prison"]
someObject.append(["work":"soldier"]) // does not work (by that I mean there is no .append function like that of other collection types such as NSMutableArray and NSMutableDictionary
someObject = someObject + ["work":"soldier"] // does not work
I'm finding a way to make easier parameters for Alamofire since Alamofire.request uses [String : AnyObject]
The data type you have mentioned is called Dictionary. And Swift dictionary does not provide API append(_ newElement:). Dictionary is a type of hash table. Each entry in the table is identified using its key.
If you want to add new item (key,value), simply add new value under a new key like that:
object["Work"] = "Soldier"
For more information read this doc Dictionary
Try this:
someObject["work"] = "soldier" as NSString
The problem we're trying to solve is that we don't get automatic bridging from String to NSString (NSString is an AnyObject, but String is not), so we have to cross the bridge ourselves by casting.
Initialize dictionary
var dic = [String: Any]()
or
var dic : [String: Any] = ["firstName": "John", "lastName": "Doe"]
Append value
dic["age"] = 25
Update Value
dic.updateValue("Jan", forKey: "firstName")

How do I add more items to this type of name value pair array? [duplicate]

I have a simple Dictionary which is defined like:
var dict : NSDictionary = [ 1 : "abc", 2 : "cde"]
Now I want to add an element into this dictionary: 3 : "efg"
How can I append 3 : "efg" into this existing dictionary?
You're using NSDictionary. Unless you explicitly need it to be that type for some reason, I recommend using a Swift dictionary.
You can pass a Swift dictionary to any function expecting NSDictionary without any extra work, because Dictionary<> and NSDictionary seamlessly bridge to each other. The advantage of the native Swift way is that the dictionary uses generic types, so if you define it with Int as the key and String as the value, you cannot mistakenly use keys and values of different types. (The compiler checks the types on your behalf.)
Based on what I see in your code, your dictionary uses Int as the key and String as the value. To create an instance and add an item at a later time you can use this code:
var dict = [1: "abc", 2: "cde"] // dict is of type Dictionary<Int, String>
dict[3] = "efg"
If you later need to assign it to a variable of NSDictionary type, just do an explicit cast:
let nsDict = dict as! NSDictionary
And, as mentioned earlier, if you want to pass it to a function expecting NSDictionary, pass it as-is without any cast or conversion.
you can add using the following way and change Dictionary to NSMutableDictionary
dict["key"] = "value"
I know this might be coming very late, but it may prove useful to someone.
So for appending key value pairs to dictionaries in swift, you can use updateValue(value: , forKey: ) method as follows :
var dict = [ 1 : "abc", 2 : "cde"]
dict.updateValue("efg", forKey: 3)
print(dict)
SWIFT 3 - XCODE 8.1
var dictionary = [Int:String]()
dictionary.updateValue(value: "Hola", forKey: 1)
dictionary.updateValue(value: "Hello", forKey: 2)
dictionary.updateValue(value: "Aloha", forKey: 3)
So, your dictionary contains:
dictionary[1: Hola, 2: Hello, 3: Aloha]
If your dictionary is Int to String you can do simply:
dict[3] = "efg"
If you mean adding elements to the value of the dictionary a possible solution:
var dict = Dictionary<String, Array<Int>>()
dict["key"]! += [1]
dict["key"]!.append(1)
dict["key"]?.append(1)
Swift 3+
Example to assign new values to Dictionary. You need to declare it as NSMutableDictionary:
var myDictionary: NSMutableDictionary = [:]
let newValue = 1
myDictionary["newKey"] = newValue
print(myDictionary)
For whoever reading this for swift 5.1+
// 1. Using updateValue to update the given key or add new if doesn't exist
var dictionary = [Int:String]()
dictionary.updateValue("egf", forKey: 3)
// 2. Using a dictionary[key]
var dictionary = [Int:String]()
dictionary[key] = "value"
// 3. Using subscript and mutating append for the value
var dictionary = [Int:[String]]()
dictionary[key, default: ["val"]].append("value")
In Swift, if you are using NSDictionary, you can use setValue:
dict.setValue("value", forKey: "key")
Given two dictionaries as below:
var dic1 = ["a": 1, "c": 2]
var dic2 = ["e": 3, "f": 4]
Here is how you can add all the items from dic2 to dic1:
dic2.forEach {
dic1[$0.key] = $0.value
}
Dict.updateValue updates value for existing key from dictionary or adds new new key-value pair if key does not exists.
Example-
var caseStatusParams: [String: AnyObject] = ["userId" : UserDefault.userID ]
caseStatusParams.updateValue("Hello" as AnyObject, forKey: "otherNotes")
Result-
▿ : 2 elements
- key : "userId"
- value : 866
▿ : 2 elements
- key : "otherNotes"
- value : "Hello"
[String:Any]
For the fellows using [String:Any] instead of Dictionary below is the extension
extension Dictionary where Key == String, Value == Any {
mutating func append(anotherDict:[String:Any]) {
for (key, value) in anotherDict {
self.updateValue(value, forKey: key)
}
}
}
As of Swift 5, the following code collection works.
// main dict to start with
var myDict : Dictionary = [ 1 : "abc", 2 : "cde"]
// dict(s) to be added to main dict
let myDictToMergeWith : Dictionary = [ 5 : "l m n"]
let myDictUpdated : Dictionary = [ 5 : "lmn"]
let myDictToBeMapped : Dictionary = [ 6 : "opq"]
myDict[3]="fgh"
myDict.updateValue("ijk", forKey: 4)
myDict.merge(myDictToMergeWith){(current, _) in current}
print(myDict)
myDict.merge(myDictUpdated){(_, new) in new}
print(myDict)
myDictToBeMapped.map {
myDict[$0.0] = $0.1
}
print(myDict)
To add new elements just set:
listParameters["your parameter"] = value
There is no function to append the data in dictionary. You just assign the value against new key in existing dictionary. it will automatically add value to the dictionary.
var param = ["Name":"Aloha","user" : "Aloha 2"]
param["questions"] = "Are you mine?"
print(param)
The output will be like
["Name":"Aloha","user" : "Aloha 2","questions" : ""Are you mine"?"]
To append a new key-value pair to a dictionary you simply have to set the value for the key. for eg.
// Initialize the Dictionary
var dict = ["name": "John", "surname": "Doe"]
// Add a new key with a value
dict["email"] = "john.doe#email.com"
print(dict)
Output -> ["surname": "Doe", "name": "John", "email": "john.doe#email.com"]
var dict = ["name": "Samira", "surname": "Sami"]
// Add a new enter code herekey with a value
dict["email"] = "sample#email.com"
print(dict)
Up till now the best way I have found to append data to a dictionary by using one of the higher order functions of Swift i.e. "reduce". Follow below code snippet:
newDictionary = oldDictionary.reduce(*newDictionary*) { r, e in var r = r; r[e.0] = e.1; return r }
#Dharmesh In your case, it will be,
newDictionary = dict.reduce([3 : "efg"]) { r, e in var r = r; r[e.0] = e.1; return r }
Please let me know if you find any issues in using above syntax.
Swift 5 happy coding
var tempDicData = NSMutableDictionary()
for temp in answerList {
tempDicData.setValue("your value", forKey: "your key")
}
I added Dictionary extension
extension Dictionary {
func cloneWith(_ dict: [Key: Value]) -> [Key: Value] {
var result = self
dict.forEach { key, value in result[key] = value }
return result
}
}
you can use cloneWith like this
newDictionary = dict.reduce([3 : "efg"]) { r, e in r.cloneWith(e) }
if you want to modify or update NSDictionary then
first of all typecast it as NSMutableDictionary
let newdictionary = NSDictionary as NSMutableDictionary
then simply use
newdictionary.setValue(value: AnyObject?, forKey: String)

Saving more than one value to a Dictionary key in a loop with an Array

I have this block of code
//start of the loop
if let objects = objects as? [PFObject] {
for object in objects {
//saving the object
self.likerNames.setObject(object["fromUserName"]!, forKey: saveStatusId!)
}
}
likerNames is an NSMutableArray declared earlier, saveStatusId is a string I also declared and saved earlier (It's just an objectId as a String), and object["fromUserName"] is an object returned from my query (not shown above).
Everything is working fine as it is but my query sometimes returns more than one object["fromUserName"] to the same key which is saveStatusId. When this happens the value I have for that saveStatusId is replaced when I actually want it to be added to the key.
So want it to kind of look like this
("jKd98jDF" : {"Joe", "John"})
("ksd6fsFs" : {"Sarah"})
("payqw324" : {"Chris", "Sarah", "John"})
I know you can use Arrays but I'm not sure how I would go about that to get it to work in my current situation.
So my question would be how to I get my key (saveStatusId) to store more than one value of object["fromUserName"]?
Something like this could work
let key = saveStatusId!
let oldValue = self.likerNames.objectForKey( key ) as? [String]
let newValue = (oldValue ?? []) + [ object["fromUserName" ] ]
self.likerNames.setObject( newValue, forKey: key )
If likerNames has an array in slot[saveStatusId], append the new value, otherwise create an array and put that in the right slot

How to 'switch' based on keys contained in a dictionary in Swift?

I want to execute different branches based on what keys a dictionary contains, here's some code you can paste into a playground that shows what I currently do:
let dict1 = ["a" : 1, "thingy" : 2]
let dict2 = ["b" : 3, "wotsit" : 4]
let dict = dict1 // Change this line to see different outcomes
if let valueA = dict["a"],
let thingy = dict["thingy"] {
// Code for type with "a" and "thingy" keys
println("a/thingy")
} else if let valueB = dict["b"],
let wotsit = dict["wotsit"] {
// Code for type with "b" and "wotsit" keys
println("b/wotsit")
}
However, I think this would be more elegantly expressed as a switch statement - something like this:
let dict1 = ["a" : 1, "thingy" : 2]
let dict2 = ["b" : 3, "wotsit" : 4]
let dict = dict1 // Change this line to see different outcomes
switch dict {
case let a = dict["a"],
let thingy = dict["thingy"]:
// Code for type with "a" and "thingy" keys
println("a/thingy")
case let b = dict["b"],
let wotsit = dict["wotsit"]:
// Code for type with "b" and "wotsit" keys
println("b/wotsit")
default:
break
}
I have tried the above and various other attempts to express this logic in a switch but couldn't make it work. So how could I do this in a switch (or is this misguided in some way)?
Background:
The dictionaries are actually SwiftyJSON JSON objects loaded from JSON data, and I want to infer the 'type' of object these JSON structures represent, from what keys they contain - if they don't contain all the right keys for a particular object they won't attempt to load as that type. I could add a "type" to each JSON structure and switch based on that value, but I'd prefer to automatically infer their type from the keys as I currently do.