Appending dictionary items in to Array<Dictionary<String, String>> - swift

Let me create these 3 dictionaries:
var animal1 = ["name":"lion", "footCount":"4", "move":"run"]
var animal2 = ["name":"Fish", "footCount":"0", "move":"swim"]
var animal3 = ["name":"bird", "footCount":"2", "move":"fly"]
And then let me create this array:
var myArray= [[String : String]()]
and then let me append above dictionaries in to myArray
myArray.append(animal1)
myArray.append(animal2)
myArray.append(animal3)
I see 4 items if I run below code
print(myArray.count)
because the array is created with one empty item: var myArray= [[String : String]()]
So I need to use below code all the time:
myArray.removeFirst()
My question is:
Is there another alternative array defination to append above dictionaries? Because I must execute above code all the time if I use this array defination:
var myArray= [[String : String]()]

You can create an empty array of dictionaries like this:
var myArray= [[String : String]]()
Note that the ()s are outside of the outer []s. Your attempt of [String : String]()] is an array literal containing one element of an empty dictionary, whereas you should be calling the initialiser for the array type of [[String : String]] (aka Array<Dictionary<String, String>>).
Since you have all the elements you want in the array already, you could just do:
var myArray = [animal1, animal2, animal3]
as well.
Seeing how all your dictionary keys are the same though, you should really create a custom struct for this:
struct Animal {
let name: String
let footCount: Int
let move: String
}
And your array can be:
var myArray= [Animal]()

Related

appending key value pair to existing dictionary values in 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

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

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.

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 })]

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