I have a dictionary of type [String: Any] and I cannot get the total number of elements of internal dictionary.
struct ICP {
let staff = [
"teachers": [
[
"name": "Teacher One"
],
[
"name": "Teacher Two"
],
[
"name": "Teacher Three"
],
[
"name": "Teacher Four"
]
]
] as [String : Any]
}
I need to get the total number of teachers from the above dictionary.
First of all inside ICP struct you declared a constant variable named staff which contains a dictionary of kind [String: [[String: String]]] or shortly [String: [Any]], when you access teachers then you have a collection of single dictionaries which is kind of [[String: String]].
I suggest you to create a method inside the ICP class and call it teachersCount
Swift 5.1
Like:
struct ICP {
func teachersCount() -> Int {
guard let teachers = staff["teachers"] as? [[String: String]] else {return 0}
return teachers.count
}
You can call it outside of struct like:
ICP().teachersCount()
And Inside your struct like:
self.teachersCount()
Related
I am trying to create an array with keys from a dictionary based on certain values from it. The dictionary that I have is employees_main.json and looks something like this:
{
"John Doe": {
"role": "Engineer",
"location": "Europe",
"isEmployedFullTime": true
},
"Jane Doe": {
"role": "Manager",
"location": "Europe",
"isEmployedFullTime": true
},
"U.N. Owen": {
"role": "Tech",
"location": "Europe",
"isEmployedFullTime": false
}
}
To load it into Swift I have create a Struct in a file called Employee.swift, as well as a Bundle-Decodable.swift file, and it loaded correctly.
struct Employee: Codable {
let role: String
let location: String
let isEmployedFullTime: Bool
}
Now in my ContentView I am trying to import the dictionary into an array of keys. My current code looks so:
struct ContentView: View {
#State private var employees = Bundle.main.decode("employees_main.json")
var employees_names: [String] {
employess.map(\.key)
}
}
This works in creating an array of the keys, but the array is shuffled every time it is called, breaking code further down which assumes a static structure, e.g. employees_names[1] will always be "Jane Doe". The second thing is I want to only get the keys where isEmployedFullTime is set to true, however I am not sure on how that if statement would look like in this.
struct Country {
var translations : [String:String?]? // must be defined as optionals!
}
// example entry
translationsDict = [
"translations": [
"de":"Deutschland",
"en": "germany",
"it": nil
]
]
How can I extract the values "Deutschland" and "germany" into a new array?
result should be:
["germany", "Deutschland"]
Firstly, get a collection of all values of translations, then convert it to an array.
if let collection = translationsDict["translations"]?.values {
let array = Array(collection)
print(array)
}
or
if let array = translationsDict["translations"]?.map({ $0.1 }) {
print(array)
}
Usually I just step into the dictionary and find the value once inside. In this case, I need to step in, loop through to find a value then step back out again then find a different value. Example:
address_components": [
{
"long_name": "E3 2AA",
"short_name": "E3 2AA",
"types": [
"postal_code"
]
},
{
"long_name": "London",
"short_name": "London",
"types": [
"postal_town"
]
}
]
This is what googles api dictionary looks like and I need to fetch the long_name of the postal_town.
You can use the first(where: function passing a closure to filter for the type, this avoids a loop:
if let addressComponents = json["address_components"] as? [[String:Any]],
let postalTownComponent = addressComponents.first(where: { ($0["types"] as! [String]).contains("postal_town") }) {
print(postalTownComponent["long_name"])
}
This should do it for you:
let result = addressComponents.filter({ return ($0["types"] as! [String]).contains("postal_town") }).map({ $0["long_name"] })
address_components is an array so you can just loop over it and check the value of your key. Maybe something like:
var names = []
for entry in addressComponent {
if addressComponent["types"][0] == "postal_town" {
names.append(addressComponent["long_name"])
}
}
Should it just that simple, or I misunderstand your question? An example:
let dict = [ "long_name": "E3 2AA", "short_name": "E3 2AA"]
for (key, value) in dict {
print("your key: \(key) and value: \(value)")
}
I have response from server I want to filter it and store in array using swift. Please help how to do it.
self.countryArrayvalue = (json?["list"] as! [Dictionary<String, Any>] as! NSArray) as! [Dictionary<String, Any>]
now i want to get country name from this self.countryArrayvalue and store in array.
Response is:
{
"error": false,
"error_code": 200,
"list": [
{
"country_id": "1",
"country_name": "Afghanistan",
"iso_code": "AF"
},
{
"country_id": "2",
"country_name": "Aland Islands",
"iso_code": "AX"
},
{
"country_id": "3",
"country_name": "Albania",
"iso_code": "AL"
} ]
}
You are making too many casting instead of single one.
self.countryArrayvalue = json?["list"] as! [[String: Any]]
Now to get array of country name try like this way.
self.countryNamesArray = self.countryArrayvalue.flatMap { $0["country_name"] as? String }
I've got an object in Swift that is a dictionary of type Dictionary<String, String[]>. I'd like to be able to filter the String[] array whilst maintaining the dictionary structure.
let list: Dictionary<String, String[]> = [
"Vegetables" : [ "Carrot", "Potato" ],
"Fruit" : [ "Apple", "Orange", "Banana" ]
]
I'd like to be able to filter for everything containing an "O", and end up with something that looks like this:
[
"Vegetables" : [ "Carrot", "Potato" ],
"Fruit" : [ "Orange" ]
]
To filter the arrays, I've been doing this:
["Carrot", "Potato"].filter { ($0 as NSString).containsString("o") }
However, the part I'm struggling with now is mapping over the dictionary - because then I can preserve the key and call that filter function on the value. How would I go about doing this? Thanks in advance!
You can do it in a for in loop:
for (key, array) in list {
list[key] = array.filter { ($0 as NSString).containsString("o") }
}
You can also add your own map method to Dictionary:
extension Dictionary {
func map(f: (KeyType, ValueType) -> ValueType) -> [KeyType:ValueType] {
var ret = [KeyType:ValueType]()
for (key, value) in self {
ret[key] = f(key, value)
}
return ret
}
}
Then you can simply do:
var filteredList = list.map { $1.filter { ($0 as NSString).containsString("o") } }
Note: My implementation of map on Dictionary returns a copy of the dictionary to be more like the map method of Array
You can enumerate it and filter in 1 go. I just made list a variable instead of a const to make it simpler. Here is the code:
//it's a variable
var list: Dictionary<String, String[]> = [
"Vegetables" : [ "Carrot", "Potato" ],
"Fruit" : [ "Apple", "Orange", "Banana" ]
]
for (key, array) in list {
list[key] = array.filter({
(x : String) -> Bool in
return !(x.rangeOfString("o", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil, locale: nil).isEmpty)
})
}
NSLog("%#", list)
The output will be :
{
Fruit = (
Orange
);
Vegetables = (
Carrot,
Potato
);
}