How to fetch data from array of Dictionary - swift - ios

How can I fetch data from this array?
Here there is an array which contains some key value pairs, and some keys contain an array of dictionary.
var dataArray = [
["teamName":"Arsenal",
"image":"imageName",
"nextMatch":"in 2 days",
"matches":[
["oppositeTeam":"teamName",
"matchTimings":"121212",
"matchId":"ID 213432"],
["oppositeTeam":"teamName",
"matchTimings":"121212",
"matchId":"ID 213432"]
],
"fixtures":[
["oppositeTeam":"teamName",
"oppositeTeamScore":"7",
"HomeTeamScore":"4",
"HomeTeamCards":"True",
"oppositeTeamCards":"false",
"fixturesId":"ID 213432"],
]
],["teamName":"Chelsea",
"image":"imageName",
"nextMatch":"in 2 days",
"matches":[["oppositeTeam":"teamName",
"matchTimings":"121212",
"matchId":"ID 213432"],["oppositeTeam":"teamName",
"matchTimings":"121212",
"matchId":"ID 213432"]
],"fixtures":[["oppositeTeam":"teamName",
"oppositeTeamScore":"7",
"HomeTeamScore":"4",
"HomeTeamCards":"True",
"oppositeTeamCards":"false",
"fixturesId":"ID 213432"],["oppositeTeam":"teamName",
"oppositeTeamScore":"7",
"HomeTeamScore":"4",
"HomeTeamCards":"True",
"oppositeTeamCards":"false",
"fixturesId":"ID 213432"]
]
],["teamName":"India",
"image":"imageName",
"nextMatch":"null",
"matches":[],
"fixtures":[]
]]
I tried but I was unable to fetch data from this array.

You need to use a Model like this
struct Team {
let teamName:String
let image:String
let nextMatch:String
let matches:[Match]?
let fixtures:[Fixture]?
}
struct Match {
let oppositeTeam:String
let matchTimings:String
let matchId:String
}
struct Fixture {
let oppositeTeam:String
let oppositeTeamScore:String
let HomeTeamScore:String
let HomeTeamCards:String
let oppositeTeamCards:String
let fixturesId:String
}
Next you need to learn about Codeable in swift for which I have attached an article below
Codeable Tutorial in swift

Here is how you can access the arrays/dictionaries defined in your dataArray:
// To access team object at zero index
if let team = dataArray[0] as? [String: Any] {
print("Team: \(team["teamName"])")
// To access matches array of team object at zero index
if let matches = team["matches"] as? [[String: Any]] {
print( matches)
// To access first match
if let match = matches.first {
print(match)
}
}
// Similar to matches access fixtures
if let fixtures = dataArray[0]["fixtures"] as? [[String: Any]] {
print(fixtures)
// To access first fixture
if let fixture = fixtures.first {
print(fixture)
}
}
}
This is ok if you are just prototyping. If you plan to extend this into an actual app creating separate models is the best approach.
You can have a Team model that can contain team name, image and matches and fixtures. For matches you can create a model with matche information in it. Similarly you can create a model for fixtures as well. Your Team class will then contain arrays of Match and Fixture classes like this:
var matches: [Match]
var fixtures: [Fixture]
and your dataArray will be of type
var dataArray: [Team]

Create model for your data using Codable. Parse the data in model using JSON decoder. Then you can use your model wherever you want.
For JSON parsing, you can refer this tutorial:-
https://medium.com/xcblog/painless-json-parsing-with-swift-codable-2c0beaeb21c1

You can fetch data from your Array like this:
for attributesObj in dataArray{
let dicFrmArray = attributesObj as! NSDictionary
if ((dicFrmArray["teamName"] as? NSNull) == nil && dicFrmArray["teamName"] != nil){
print(dicFrmArray[teamName"])
}
}

Related

Filter dictionary of array objects

I am trying to filter my dictionary according to user input in UISearchController. I have following model and array of objects.
struct People {
var name: String
var id: Int
}
let first = People(name: "Atalay", id: 1)
let second = People(name: "Ahmet", id: 2)
let third = People(name: "Mehmet", id: 3)
let fourth = People(name: "Yusuf", id: 4)
let peoples: [People] = [first, second, third, fourth, fifth]
I put them into a dictionary to create section indexed table view with following code.
var dict: [String: [People]] = Dictionary(grouping: peoples, by: { (people) -> String in
return String(people.name.prefix(1))
})
Above code gives me a dictionary with first letter of People names. Now, I would like to filter my array according to user input. However, I tried following code for filtering but it is not working as I expected.
let filteredDict = (dict.filter { $0.1.contains { $0.name.lowercased().contains("ata") } })
It returns all "A" letter section indexes like ["A": People(name: "Atalay", id: 1), People(name: "Ahmet", id: 2)]
How can I achieve filter also my array inside dictionary?
If I'm not mistaken, you want your final dictionary to have all the keys and only the filtered array of items as the values. If that is right, reduce is the tool for that:
let filtered = dict.reduce(into: [String: [People]]()) {
$0[$1.key] = $1.value.filter { $0.name.lowercased().contains("ata") }
}
I decided it was simplest to get this right by using an old fashioned for loop and filter each group separately
var filtered = [String: [People]]()
for (k, v) in dict {
let result = v.filter {$0.name.lowercased().contains("ata")}
if result.count > 0 {
filtered[k] = result
}
}
Note that if you want to keep all the groups in the result dictionary just skip the if result.count > 0 condition
How can I achieve filter also my array inside dictionary?
You should have an array first, you can use flatMap to group all the values in your filteredDict
let array = filteredDict.flatMap { $0.value }
Then you just filter the array as usually
let filteredArray = array.filter { $0.name.lowercased().contains("ata") }

Save Nested Dictionary in UserDefaults and manage the duplication check [Swift 4.2]

I have a nested Dictionary required to save in UserDefaults and share to extension. The dictionary structure like below:
let dict = [
"Sections" : [
["Title" : "Title1", "Items": ["item1-1", "item1-2", "item1-3"]],
["Title" : "Title2", "Items": ["item2-1", "item2-2", "item2-3", "item2-4"]],
["Title" : "Title3", "Items": ["item3-1"]],
]
]
Which saved successfully with:
UserDefaults(suiteName: "group.identifier.test")!.setValue(dict, forKey: "savedDict")
But now I wish to get it back and check is Title2 already exists, if yes then delete it and add again with new Items
I used to do following but can't get the Title back:
let savedDict:[String:AnyObject] = UserDefaults(suiteName: "group.identifier.test")!.object(forKey: "savedDict") as! Dictionary
success to get the data under "Sections" by following code
let savedSection = savedDict["Sections"]
print("Saved Section: \(savedSection)")
but not able to get the Title with:
print("Saved Title: \(savedSection!["Title"])") *// return nil*
I tried for (key, value) too, but fired a data type error
for (key, value) in savedSection{ *// Type 'AnyObject?' does not conform to protocol 'Sequence'*
print("Key: \(key) Value: \(value)")
}
May I know is there any way to get the "Title" back for checking and update? Am I using the wrong way to store this kind of nested data?
Many Thanks!
in your code
print("Saved Title: \(savedSection!["Title"])") *// return nil*
here it should be
if let savedSection = savedDict["Sections"] as? [[String : Any]] { //EDIT***
print("Saved Title: \(savedSection[0]["Title"])") *// inplace of 0 any index you want,
}
as if now in your dictionary there are three elements in section so it safe to get value at 0, hope you understood that the underlying dictionary is array of dictionary in sections key, also instead of using dictionary you can use struct or class to save your data and while getting it retrieve it as that struct type.
First of all, never use KVC method setValue(:forKey with UserDefaults.
There is generic set(:forKey. And there is dictionary(forKey: to get a [String:Any] dictionary back
The value for key Sections is an array (index-based). Lets assume you have this new data
let newTitle2 : [String:Any] = ["Title" : "Title2", "Items": ["item4-1", "item4-2", "item4-3"]]
This is a way to load the dictionary – you should always safely check if the dictionary exists – update it and save it back. If the item for "Title2" exists it will be overwritten otherwise the new item is appended to the array.
let groupDefaults = UserDefaults(suiteName: "group.identifier.test")!
if var savedDict = groupDefaults.dictionary(forKey: "savedDict"),
var sections = savedDict["Sections"] as? [[String:Any]] {
if let title2Index = sections.firstIndex(where: {($0["Title"] as! String) == "Title2"}) {
sections[title2Index] = newTitle2
} else {
sections.append(newTitle2)
}
savedDict["Sections"] = sections
groupDefaults.set(savedDict, forKey: "savedDict")
}

Taking out array from dictionary in swift 3

Hi I am trying to populate a view using the response obtained from service but not able to fetch the exact value out of the whole response ,
[
["product_id": PRO161519,
"name": clothes,
"brand_name": Levis,
"discountprice": 0,
"images": <__NSArrayM 0x6000002541c0>(
{
image = "HTTP://i.vinove.com/dnn/backend/uploads/954tshirt_PNG5434.png";
}
)
"category": Accessories,
"price": 23.00
]
]
ProductList-Model
import UIKit
import SpeedLog
let KImages = "images"
let KListImage = "image"
struct ProductList{
var images = ""
var itemArray = [String]()
func bindProductListDataToPopulateView(_ response:[[String:Any]])->[ProductList]{
SpeedLog.print("response value as result",response)
for items in response{
print("items values",items)
}
print("item array",itemArray)
return []
}
}
response value as result
[["image":
item Values
["image":
Kindly help me to get the values images here.
You have to use like this :
for product in products {
if let productImages = product["images"], let images = productImages as? NSArray {
for image in images {
if let image = image as? [String: String] {
print(image["image"])
}
}
}
}
More than likely that JSON response you posted will eventually find its way to you in the form of a key-value Dictionary. You then use a "key" from the JSON you posted to extract the key's corresponding "value". In the snippet you posted, the keys would be the values on the left of the colon (e.g. "product_id", "name", etc).
Now, lets say your dictionary of key-values was called "jsonDictionary". You then would extract the values like so:
let productId = jsonDictionary["product_id"]
let name = jsonDictionary["name"]
If, however, you don't have logic to deserialize that raw JSON data (that you posted in your question) into a Dictionary, then you'll have to start there instead.

Getting the Key value for a complex nested dictionary/ array combination in Swift

I am trying to access the keys for the following Dictionary:
let dictionaryToUSe = ["Starter":["mealName":"hamburger","price":"20.00"],"MainCourse":["mealName":"hotdog","price":"30.00"] ]
let keysToUse = dictionaryToUSe.keys
print(keysToUse) // returns "LazyMapCollection<Dictionary<String, Dictionary<String, String>>, String>(_base: ["Starter": ["price": "20.00", "mealName": "hamburger"]], _transform: (Function))\n"
How do I access the "starter" string?
and how do I generate a list of the keys for the "dictionaryToUSe" Dictionary?
To get the list of the dictionary keys, generate an array from the LazyMapCollection:
let keysToUse = Array(dictionaryToUSe.keys)
Result:
["Starter", "MainCourse"]
But to access the values from the dictionary, use classic subscripting:
if let starter = dictionaryToUSe["Starter"] {
print(starter) // ["price": "20.00", "mealName": "hamburger"]
if let price = starter["price"] {
print(price) // "20.00"
}
// etc
}

How to append associative array elements in Swift

How do I create and append to an associative array in Swift? I would think it should be something like the following (note that some values are strings and others are numbers):
var myArray = []
var make = "chevy"
var year = 2008
var color = "red"
myArray.append("trackMake":make,"trackYear":year,"trackColor":color)
The goal is to be able to have an array full of results where I can make a call such as:
println(myArray[0]["trackMake"]) //and get chevy
println(myArray[0]["trackColor"]) //and get red
Simply like this:
myArray.append(["trackMake":make,"trackYear":year,"trackColor":color])
Add the brackets. This will make it a hash and append that to the array.
In such cases make (extensive) use of let:
let dict = ["trackMake":make,"trackYear":year,"trackColor":color]
myArray.append(dict)
The above assumes that your myArray has been declared as
var myArray = [[String:AnyObject]]()
so the compiler knows that it will take dictionary elements.
I accept above answer.It is good.Even you have given correct answer,I like to give simplest way.The following steps are useful,if you guys follow that.Also if someone new in swift and if they go through this,they can easily understand the steps.
STEP 1 : Declare and initialize the variables
var array = Array<AnyObject>()
var dict = Dictionary<String, AnyObject>()
var make = "chevy"
var year = 2008
var color = "red"
STEP 2 : Set the Dictionary(adding keys and Values)
dict["trackMake"] = make
dict["trackYear"] = year
dict["trackColor"] = color
println("the dict is-\(dict)")
STEP 3 : Append the Dictionary to Array
array.append(dict)
println("the array is-\(array)")
STEP 4 : Get Array values to variable(create the variable for getting value)
let getMakeValue = array[0]["trackMake"]
let getYearValue = array[0]["trackYear"]
let getColorValue = array[0]["trackColor"]
println("the getMakeValue is - \(getMakeValue)")
println("the getYearValue is - \(getYearValue)")
println("the getColorVlaue is - \(getColorValue)")
STEP 5: If you want to get values to string, do the following steps
var stringMakeValue:String = getMakeValue as String
var stringYearValue:String = ("\(getYearValue as Int)")
var stringColorValue:String = getColorValue as String
println("the stringMakeValue is - \(stringMakeValue)")
println("the stringYearValue is - \(stringYearValue)")
println("the stringColorValue is - \(stringColorValue)")
STEP 6 : Finally the total output values are
the dict is-[trackMake: chevy, trackColor: red, trackYear: 2008]
the array is-[{
trackColor = red;
trackMake = chevy;
trackYear = 2008;
}]
the getMakeValue is - Optional(chevy)
the getYearValue is - Optional(2008)
the getColorVlaue is - Optional(red)
the stringMakeValue is - chevy
the stringYearValue is - 2008
the stringColorValue is - red
Thank You
This sounds like you are wanting an array of objects that represent vehicles. You can either have an array of dictionaries or an array of vehicle objects.
Likely you will want to go with an object as Swift arrays and dictionaries must be typed. So your dictionary with string keys to values of differing types would end up having the type [String : Any] and you would be stuck casting back and forth. This would make your array of type [[String : Any ]].
Using an object you would just have an array of that type. Say your vehicle object's type is named Vehicle, that would make your array of type [Vehicle] and each array access would return an instance of that type.
If I want to try it with my own statement. Which also I want to extend my array with the data in my dictionary and print just the key from dictionary:
var myArray = ["Abdurrahman","Yomna"]
var myDic: [String: Any] = [
"ahmed": 23,
"amal": 33,
"fahdad": 88]
for index in 1...3 {
let dict: [String: Any] = [
"key": "new value"
]
// get existing items, or create new array if doesn't exist
var existingItems = myDic[myArray] as? [[String: Any]] ?? [[String: Any]]()
// append the item
existingItems.append(myArray)
// replace back into `data`
myDic[myArray] = existingItems
}

Resources