appending key value pair to existing dictionary values in swift - swift

I'm trying achieve below results. Where I can save multiple key values for multiple string items.
//dict["Setting1"] = ["key1":"val1"]
//dict["Setting1"] = ["key2":"val2"]
//dict["Setting2"] = ["key1":"val1"]
//dict["Setting2"] = ["key2":"val2"]
// and so on..
//or
//dict["Setting1"].append(["key2":"val2"]) // this doesn't work
//accessing dict["Settings1"]["key1"] ..should give me val1
var dict = [String:[String:String]]()
var lst1 = ["key2":"val2"]
dict["one"] = ["key1":"val1"]
dict["one"]?.append(lst1)
print(dict)
gives me error
error: value of type '[String : String]' has no member 'append'
obj["one"]?.append(lst1)
~~~~~~~~~~~ ^~~~~~

You're using a Dictionary which doesn't have methods like append(_:). append(:_) adds something to the end of an Array, but Dictionaries are unordered.
To add something to a Dictionary, you first define a key for it, and then assign it a value in the Dictionary
It'll look like this:
var dict = [String :[String: String]]()
var lst1 = ["key2": "val2"]
dict["one"] = ["key1": "val1"]
But you can't append to dict["one"], because it's not an array, you can only overwrite it
dict["one"] = lst1

Related

Getting Array value in a dictionary swift

I am trying to get key and value in a Dictionary while I am able to the key and map it to a dictionary, I am unable to get the value which is an array.
var dict = [String: [String]]
I was able to get the key as an array which is what I want like:
var keyArray = self.dict.map { $0.key }
How can I get the value which is already an array
Use flatMap if you want to flatten the result you get when you use map which is of type [[String]].
let valueArray = dict.flatMap { $0.value } // gives `[String]` mapping all the values
Here is how you get each string count Array
var dict = [String: [String]]()
let countOfEachString = dict.map { $0.value }.map{ $0.count }
Each value is a string array .. so to access each array you need to use map again

Add two dictionary values in new array . the array values will remains unchanged from its position

Add two dictionary values in a new array. the array values will remain unchanged from its position. I need to add two dictionary values in a new array. The values added in the array must remain constant at every run.
var dictionary1:[String:Int] = ["Mohan":75, "Raghu":82, "John":79]
var dictionary2:[String:Int] = ["Surya":91, "John":79, "Saranya":92]
dictionary1.merge(dictionary2){(current, _) in current}
var arr : [String] = []
for (key, value) in dictionary1 { arr.append("(key) (value)") }
print(dictionary1)
Simply use append(contentsOf:) to add the contents of dictionary1 and dictionary2 to arr. Use map(_:) to format the key-value pairs while adding to the array.
let dictionary1 = ["Mohan":75, "Raghu":82, "John":79]
let dictionary2 = ["Surya":91, "John":79, "Saranya":92]
var arr = [String]()
arr.append(contentsOf: dictionary1.map({"\($0.key) \($0.value)"}))
arr.append(contentsOf: dictionary2.map({"\($0.key) \($0.value)"}))
print(arr) //["Mohan 75", "John 79", "Raghu 82", "Surya 91", "John 79", "Saranya 92"]
As apple stats, you can use KeyValuePairs to maintain ordered collection of key-value pairs and don’t require the fast key lookup that the Dictionary type provides.
let recordTimes: KeyValuePairs = ["Florence Griffith-Joyner": 10.49,
"Evelyn Ashford": 10.76,
"Evelyn Ashford": 10.79,
"Marlies Gohr": 10.81]
print(recordTimes.first!)
// Prints "("Florence Griffith-Joyner", 10.49)"
Check if it is helpful in your case.

How do I update Swift Dictionary values of mixed types, in particular Arrays

I have a dictionary of mixed types (string, NSImage, and an Array). When appending to the array, I get the error "Value of type 'Any??' has no member 'append'". I don't see how to cast "file_list" value as an Array so I can append values to it.
var dataDict: [String:Any?] = [
"data_id" : someString,
"thumbnail" : nil,
"file_list" : [],
]
// do stuff... find files... whirrr wizzzz
dataDict["thumbnail"] = NSImage(byReferencingFile: someFile)
dataDict["file_list"].append( someFile ) <- ERROR: Value of type 'Any??' has no member 'append'
You can't. You need to first get your key value, cast from Any to [String], append the new value and then assign the modified array value to your key:
if var array = dataDict["file_list"] as? [String] {
array.append(someFile)
dataDict["file_list"] = array
}
or
if let array = dataDict["file_list"] as? [String] {
dataDict["file_list"] = array + [someFile]
}
Another option is to create a custom struct as suggested in comments by OOPer

Swift dictionary, a key with multiple values

I would like to know how I can make a key of a dictionary have multiple values according to the data that comes to it.
Attached basic example:
var temp = [String: String] ()
temp ["dinningRoom"] = "Table"
temp ["dinningRoom"] = "Chair"
In this case, I always return "Chair", the last one I add, and I need to return all the items that I am adding on the same key.
In this case, the "dinningRoom" key should have two items that are "Table" and "Chair".
You can use Swift Tuples for such scenarios.
//Define you tuple with some name and attribute type
typealias MutipleValue = (firstObject: String, secondObject: String)
var dictionary = [String: MutipleValue]()
dictionary["diningRoom"] = MutipleValue(firstObject: "Chair", secondObject: "Table")
var value = dictionary["diningRoom"]
value?.firstObject
You can declare a dictionary whose value is an array and this can contain the data you want, for example:
var temp = [String: [String]]()
temp["dinningRoom"] = ["Table", "Chair", "Bottle"]
If you want to add a new element you can do it this way:
if temp["dinningRoom"] != nil {
temp["dinningRoom"]!.append("Flower")
} else {
temp["dinningRoom"] = ["Flower"]
}
Now temp["dinningRoom"] contains ["Table", "Chair", "Bottle", "Flower"]
Use Dictionary like this:
var temp = [String: Any]()
temp["dinningRoom"] = ["Table", "Chair"]
If you want to fetch all the elements from dinningRoom. You can use this:
let dinningRoomArray = temp["dinningRoom"] as? [String]
for room in dinningRoomArray{
print(room)
}
It is not compiled code but I mean to say that we can use Any as value instead of String or array of String. When you cast it from Any to [String]
using as? the app can handle the nil value.

How to Mutate an Array in a Dictionary?

I've tried the following in a Playground:
var d1 = [String: [String]]()
d1["a"] = [String]()
var a1 = d1["a"]!
a1.append("s1")
println(d1)
The output is: [a: []]
I was hoping for: [a: ["s1"]]
What would be the right way to mutate an array in a dictionary?
In swift, structures are copied by value when they get assigned to a new variable. So, when you assign a1 to the value in the dictionary it actually creates a copy. Here's the line I'm talking about:
var a1 = d1["a"]!
Once that line gets called, there are actually two lists: the list referred to by d1["a"] and the list referred to by a1. So, only the second list gets modified when you call the following line:
a1.append("s1")
When you do a print, you're printing the first list (stored as the key "a" in dictionary d1). Here are two solutions that you could use to get the expected result.
Option1: Append directly to the array inside d1.
var d1 = [String : [String]]()
d1["a"] = [String]()
d1["a"]?.append("s1")
println(d1)
Option 2: Append to a copied array and assign that value to "a" in d1.
var d1 = [String : [String]]()
d1["a"] = [String]()
var a1 = d1["a"]!
a1.append("s1")
d1["a"] = a1
println(d1)
The first solution is more performant, since it doesn't create a temporary copy of the list.
Extending the excellent answer of #jfocht here is
Option 3: Append within function where array is passed by reference
func myAdd(s : String, inout arr : [String]?) {
if arr == nil
{
arr = [String]()
}
arr?.append(s)
}
var d1 = [String : [String]]()
myAdd("s1", &d1["a"])
myAdd("s2", &d1["b"])
println(d1) // [ b: [s2], a: [s1]]
Added some sugar in the sense that it actually creates a new array if given a dictionary key with no arrays attached currently.
Swift Array and Dictionary are not an objects like NSArray and NSDictionary. They are struct. So by doing var a1 = d1["a"] would be like doing var a = point.x and then change a but of course the point.x will not change.
So by doing this instead:
d1["a"] = []
d1["a"]!.append("")
Would be like doing point.x = 10
you need to set a new value for key "a" inside your dictionary.
Which means:
d1["a"] = a1