How to create a sub-Dictionary from a Dictionary? - swift

I am wondering what is the best way to initialize a 'child' Dictionary with specified key/value pairs from a 'parent' Dictionary. As an example,
parent dictionary looks like:
["name": "Joe", "age": 45, "occupation": scientist]
Now I want to quickly create a child dictionary that only uses the "name" and "age" kv pairs
child dictionary should look like:
["name": "Joe", "age": 45]
Is there a supported Swift dictionary function that can do this? Thanks

One way to do it is to filter the dictionary:
let dict: [String : Any] = ["name": "Joe", "age": 45, "occupation": "scientist"]
let newkeys = ["name", "age"]
let newdict = dict.filter { newkeys.contains($0.key) }
If your original dictionary is large, and the new keys are small by comparison, it might be quicker to construct a new dict like so:
let newdict = newkeys.reduce(into: [:]) { $0[$1] = dict[$1] }

Related

Create dictionary with objects and array statically and get their value

I am trying to create a dictionary in a static way and obtain the data, but I am not correct. I mean because it is only an array of string and any, but in the image it has brackets and braces. Any help I will appreciate a lot, thanks for your time
let responseDevice : [String : Any] = [
"date_s" : "2021-02-18",
"id_c" : "4",
"id_d" : 1,
"data" : [
"Peso" : 34,
"Fc" : -1,
"Age" : 34,
"Name" : "July"
],
"flags" : 0,
"error" : 0
]
if let date_s = responseDevice["date_s"] as? String,
let dat = responseDevice["data"] as? [String : Any],
let peso = dat["Peso"] as? Int {
print(date_s)
print(peso)
}
print("log :\(responseDevice)")
result:
2021-02-18
34
log :["id_c": "4", "error": 0, "id_d": 1, "flags": 0, "date_s": "2021-02-18", "data": ["Peso": 34, "Fc": -1, "Age": 34, "Name": "July"]]
What you created is a Swift Dictionary. What you have on that image is JSON Object. It's not very clear what your goal is, so couple of basic pointers:
If you want to parse JSON into Dictionary, check this answer
If you simply want to include some JSON sample in your code (e.g. for testing), you can put it in triple quotes:
var myJSON = """
[paste your JSON here]
"""

Sort Dictionary [Key: [Key: Value]] by value - Swift

I have a dictonary that looks like this:
var dict = [Int: [String: Any]]()
dict[1] = ["nausea": 23, "other": "hhh"]
dict[2] = ["nausea": 3, "other": "kkk"]
dict[3] = ["nausea": 33, "other" : "yyy"]
I want to sort the dictionary by the value of the dictionary value for key "nausea" from least to greatest.
To look like this:
sortedDict = [2: ["nausea": 3, "other": "kkk"], 1: ["nausea": 23, "other": "hhh"], 3: ["nausea": 33, "other" : "yyy"]]
I tried to play around with it using .sort():
let sortedDict = dict.sort( { ($0["nausea"] as! Int) > ($1["nausea"] as! Int) })
but, obviously It didn't work because "nausea" isn't the key for the dictonary
Can someone show me how they would do this?
Thanks in advance!
A Dictionary is unordered by design, as the documentation clearly states:
Every dictionary is an unordered collection of key-value pairs.
You are probably looking for an ordered type like Array.
var arrayDict = [
["nausea": 23, "other": "hhh"],
["nausea": 3, "other": "kkk"],
["nausea": 33, "other" : "yyy"]
]
let sorted = arrayDict.sorted { $0["nausea"] as! Int < $1["nausea"] as! Int }
print(sorted)
Update: Even better as #LeoDabus suggested in the comment you can use an array of custom objects:
struct MyObject {
var nausea: Int
var other: String
}
var array = [
MyObject(nausea: 23, other: "hhh"),
MyObject(nausea: 3, other: "kkk"),
MyObject(nausea: 33, other: "yyy")
]
let sorted = array.sorted { $0.nausea < $1.nausea }
print(sorted)

Alamofire multi parameters dictionary

Hi i am trying to give to alamofire parameters called "addons" that are in array...array can contain 3 or X items. I am trying to use FOR cycle to ad dictionary to another another one set of items, but...it only shows the last one...that seems it override the previous one. I tried everything I know...Even try to use SwiftyJSON framework....but alamofire only take pure dictionary type.
let itemsArr = ["Skirts", "Coat", "Shirt"]
let priceArr = ["7.00", "7.00", "2.90"]
let quantityArr = ["2", "5", "1"]
let personalInfo: [String : Any] = [
"phone" : phone,
"notes" : descNote
]
var para: [String: Any] = [
"pieces" : pieces,
"personal_info" : personalInfo,
"payment_method" : paymentMethod
]
for i in 0..<itemsArr.count {
let addons: [String: Any] = [
"name":itemsArr[i],
"price":priceArr[i],
"quantity":quantityArr[i]
]
print(addons)
para["addons"] = addons
}
well I need something like this
{
"pieces": 12,
"personal_info": {
"phone": "+420783199102",
"notes": "Plz be fast, I need to play Game of War"
},
"payment_method": "cod",
"addons": [
{
"name": "Select day Tue",
"price": 3.5,
"quantity": 1
},
{
"name": "Select day Thu",
"price": 3.5,
"quantity": 1
}
]
}
Your problem is that in loop you are overwriting variable every single iteration with single result. That's why only last one is left for you.
What you should do is:
//create an array to store the addons outside of the loop
var addons: [[String: Any]] = []
for i in 0..<itemsArr.count {
let addon: [String: Any] = [
"name":itemsArr[i],
"price":priceArr[i],
"quantity":quantityArr[i]
]
//append a single addon to our array prepared before the loop
addons.append(addon)
}
//once we gathered all addons, append results to `para` dictionary
para["addons"] = addons

Dictionary wrong order - JSON

I am trying to create a dictionary that I can make into a JSON formatted object and send to the server.
Example:
var users = [
[
"First": "Albert",
"Last": "Einstein",
"Address":[
"Street": "112 Mercer Street",
"City": "Princeton"]
],
[
"First": "Marie",
"Last": "Curie",
"Address":[
"Street": "108 boulevard Kellermann",
"City": "Paris"]]
]
I use this function
func nsobjectToJSON(swiftObject: NSObject) -> NSString {
var jsonCreationError: NSError?
let jsonData: NSData = NSJSONSerialization.dataWithJSONObject(swiftObject, options: NSJSONWritingOptions.PrettyPrinted, error: &jsonCreationError)!
var strJSON = NSString()
if jsonCreationError != nil {
println("Errors: \(jsonCreationError)")
}
else {
// everything is fine and we have our json stored as an NSData object. We can convert into NSString
strJSON = NSString(data: jsonData, encoding: NSUTF8StringEncoding)!
println("\(strJSON)")
}
return strJSON
}
But my result is this:
[
{
"First" : "Albert",
"Address" : {
"Street" : "112 Mercer Street",
"City" : "Princeton"
},
"Last" : "Einstein"
},
{
"First" : "Marie",
"Address" : {
"Street" : "108 boulevard Kellermann",
"City" : "Paris"
},
"Last" : "Curie"
}
]
Problem: why is the last name last? I think it should be above address. Please let me know what I am doing wrong with the NSDictionary for this to come out wrong. Any help would be very much appreciated - thank you.
To post what has already been said in comments: Dictionaries are "unordered collections". They do not have any order at all to their key/value pairs. Period.
If you want an ordered collection, use something other than a dictionary. (an array of single-item dictionaries is one way to do it.) You can also write code that loads a dictionary's keys into a mutable array, sorts the array, then uses the sorted array of keys to fetch key/value pairs in the desired order.
You could also create your own collection type that uses strings as indexes and keeps the items in sorted order. Swift makes that straightforward, although it would be computationally expensive.
I did like this.
let stagesDict = NSDictionary()
if let strVal = sleepItemDict["stages"] as? NSDictionary {
stagesDict = strVal
let sortedKeys = (stagesDict.allKeys as! [String]).sorted(by: <)
var sortedValues : [Int] = []
for key in sortedKeys {
let value = stagesDict[key]!
print("\(key): \(value)")
sortedValues.append(value as! Int)
}
}

Swift: dictionaries inside array

Data:
[
{ firstName: "Foo", lastName: "Bar" },
{ firstName: "John", lastName: "Doe" }
]
How can I have this kind of structure using swift array and dictionary? This data shows dictionaries inside an array, right? So I suggest:
var persons:Array = [Dictionary<String, String>()]
but this gives me the error:
Cannot convert the expressions type () to type Array<T>
Any ideas?
The correct way is:
var persons = [Dictionary<String, String>]()
which is equivalent to:
var persons = [[String : String]]()
What your code does instead is to create an array filled in with an instance of Dictionary<String, String>, whereas I presume you want an empty instance of the array containing elements of Dictionary<String, String> type.
Which version of Xcode have you got?
Your code should work fine but the line:
var persons:Array = [Dictionary<String, String>()]
create the array with first empty dictionary, try this instead:
var persons:Array = [Dictionary<String, String>]()
var dic1 = ["Name" : "Jon"]
var dic2 = ["Surname" : "Smith"]
persons.append(dic1)
persons.append(dic2)
println(persons)
Are you sure you really want a dictionary within an array? The code you've given indicates more an array with named columns, which can be achieved using something like the following:
struct Name {
var firstName : String
var lastName : String
}
var persons1 : Array<Name> = [
Name(firstName: "Foo", lastName: "Bar"),
Name(firstName: "John", lastName: "Doe")
]
persons1[0].firstName // "Foo"
var persons2 : Array<(firstName: String, lastName:String)> = [
(firstName: "Mary", lastName: "Mean"),
(firstName: "Foo", lastName: "Bar"),
(firstName: "John", lastName: "Doe")
]
persons2[1].firstName // "Bar"
These are proper arrays and adressed as such using subscripts. The dictionary type is usually a combination of key and value, i.e. nickname as key, and name as value.
var nickNames : [String:String] = [
"mame" : "Mary Mean",
"foba" : "Foo Bar",
"jodo" : "John Doe"]
nickNames["mame"]! // "Mary Mean"
And here we lookup on the key value, and get an optional value in return, which I forcefully unwrapped...
All of these can be appended rather easily, but do note that the named tuple variant, persons2, is not following recommended practice. Also note that the Array of Dictionaries allow for inclusion on different keys as suggested in my last injection.
persons1.append( Name(firstName: "Some", lastName: "Guy") )
persons2.append( firstName: "Another", lastName: "Girl" )
nickNames["anna"] = "Ann Nabel"
// Array of Dictionaries
var persons : [[String:String]] = [
[ "firstName" : "Firstly", "lastName" : "Lastly"],
[ "firstName" : "Donald", "lastName" : "Duck"]
]
persons.append( ["firstName" : "Georg", "middleName" : "Friedrich", "lastName" : "Händel"] )
something like this can work for you:
var persons: Array<Dictionary<String, String>> = Array()
and now you can add the names:
persons.append(["firstName": "Foo", "lastName": "Bar"]);
persons.append(["firstName": "John", "lastName": "Doo"]);
NOTE: if you are insecure how to use literals, just don't use them.