I am currently struggling with obtaining a value from an array inside an array of dictionaries. Basically I want to grab the first "[0]" from an array stored inside an array of dictionaries. This is basically what I have:
var array = [[String:Any]]()
var hobbies:[String] = []
var dict = [String:Any]()
viewDidLoad Code:
dict["Name"] = "Andreas"
hobbies.append("Football", "Programming")
dict["Hobbies"] = hobbies
array.append(dict)
/// - However, I can only display the name, with the following code:
var name = array[0]["Name"] as! String
But I want to be able to display the first value in the array stored with the name, as well. How is this possible?
And yes; I know there's other options for this approach, but these values are coming from Firebase (child paths) - but I just need to find a way to display the array inside the array of dictionaries.
Thanks in advance.
If you know "Hobbies" is a valid key and its dictionary value is an array of String, then you can directly access the first item in that array with:
let hobby = (array[0]["Hobbies"] as! [String])[0]
but this will crash if "Hobbies" isn't a valid key or if the value isn't [String].
A safer way to access the array would be:
if let hobbies = array[0]["Hobbies"] as? [String] {
print(hobbies[0])
}
If you use a model class/struct things get easier
Given this model struct
struct Person {
let name: String
var hobbies: [String]
}
And this dictionary
var persons = [String:Person]()
This is how you put a person into the dictionary
let andreas = Person(name: "Andreas", hobbies: ["Football", "Programming"])
persons[andreas.name] = Andreas
And this is how you do retrieve it
let aPerson = persons["Andreas"]
Related
I got two arrays from API call,
One is nameArray - which contains recipe names ( menuNameArray = ["pohe","bread","cheese chilli toast"]
And another array - which contains prices of those recipes (menuPriceArray = ["10", "40", "120"].
I have got theses two arrays from API call.
I am displaying both the arrays on the table view & I am searching through the menuNamesArray because I want to search by recipe names.
I am getting recipe names by searching those from menuNameArray. Now I want menuPriceArray to get updated also according to searched menuName Array.
means if I search for "bread" then I must get price value as "40" and accordingly for other names also.
How should I perform such filtering on the second array?
My code Snippet -
//MARK: UISearch result update delegate
func updateSearchResults(for searchController: UISearchController) {
// here arrFilter is the resulting array to sotre searched items from menuNamesArray
arrFilter.removeAll(keepingCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (menuNamesArray as NSArray).filtered(using: searchPredicate)
let result = menuPriceArray.firstIndex(of: array.startIndex)
arrFilter = array as! [String]
self.tblSearch.reloadData()
//here now I got the searched menu names, Now I want prices for searched menu names from menuPrice Array..
}
Never use multiple arrays as data source.
Swift is an object oriented language. Take advantage of it.
Create a struct
struct Menu {
let name : String
let price : Double
}
and a data source array
var menues = [Menu]()
Filter the array by name and get the price, pretty easy and straightforward
if let foundMenu = menues.filter(where: {$0.name == "bread"}) {
print(foundMenu.price)
}
You can merge the two arrays into one array of dictionary elements.
for tempExportData in exportDataArray {
let tmpRegNO:NSString = (tempExportData as AnyObject).object(forKey: kRegisteredNo) as! NSString
print("tmpRegNO is",tmpRegNO)
var tmpNoArray:Array = [String]()
tmpNoArray.append(tmpRegNO as String)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
I am trying to add string value i.e tmpRegNO to the Array tmpNoArray.
In this I can able to add only one value to the array at a time.
How to add the next value to that array when it is looping for second time.
As already mentioned you have to declare the array before entering the loop.
Your code is very objectivecish. This is a swiftier version. Don't annotate types the compiler can infer and use key subscription rather than ugly casting to AnyObject and objectForKey:.
var tmpNoArray = [String]()
for tempExportData in exportDataArray {
let tmpRegNO = tempExportData[kRegisteredNo] as! String
print("tmpRegNO is",tmpRegNO)
tmpNoArray.append(tmpRegNO)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
You can even write the whole expression in one line:
let tmpNoArray = exportDataArray.flatMap { $0[kRegisteredNo] as? String }
You need move the tempNoArray initialization outside of your for in loop, if not the your array will be initialized once for every item in your exportDataArray remaining only the las item as consequence
You need something like this
var tmpNoArray:Array = [String]()
for tempExportData in exportDataArray{
if let tmpRegNO = tempExportData[kRegisteredNo] as? String
{
print("tmpRegNO is",tmpRegNO)
tmpNoArray.append(tmpRegNO as String)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
}
I've got a server response returning
(
{
agreementId = "token.virtual.4321";
city = AMSTERDAM;
displayCommonName = "bunch-of-alphanumeric";
displaySoftwareVersion = "qb2/ene/2.7.14";
houseNumber = 22;
postalCode = zip;
street = "";
}
)
how do I get the value of agreementId? response['agreementId'] is not working. i've tried some example code with .first but I cannot get it working.
Some extra information, I do a http call to a server with alamofire. I try to parse the json to a constant response:
let response = JSON as! NSDictionary
However that returns a error message
Could not cast value of type '__NSSingleObjectArrayI' (0x1083600) to 'NSDictionary' (0x108386c).
So now parse the json to an array, which seems to be working. The code above is what
let response = JSON as! NSArry
print(response)
spits out.
Now I only need to retrieve the value from the key "agreementId" and I have no clue how to do that.
In swift you need to use Swift's native type Array/[] and Dictionary/[:] instead of NSArray and NSDictionary, if you specify the type like above means more specific then the compiler won't complain. Also use optional wrapping with if let or guard let to prevent crash.
if let array = JSON as? [[String:Any]] {//Swift type array of dictionary
if let dic = array.first {
let agreementId = dic["agreementId"] as? String ?? "N/A"//Set default value instead N/A
print(agreementId)
//access the other key-value same way
}
}
Note: If you having more than one object in your array then you need to simply loop through the array to access each dictionary of array.
if let array = JSON as? [[String:Any]] {//Swift type array of dictionary
for dic in array {
let agreementId = dic["agreementId"] as? String ?? "N/A"//Set default value instead N/A
print(agreementId)
//access the other key-value same way
}
}
There are several posts on SO like this, and the only solution suggested that would seem to work is manually removing and inserting a property at the same index.
But this feels messy, and some posts suggest it's possible in Xcode 7 to directly update dictionary properties if inside an array of dictionaries.
However, it's not working for the code below, generating the Cannot assign to immutable expression of type [String:AnyObject] error.
// Class vars
var userDict = [String:AnyObject]()
var accounts = [[String:AnyObject]]()
func setHistory(index: Int, history: [String]) {
(userDict["accounts"] as! [[String:AnyObject]])[index]["history"]! = history
(userDict["accounts"] as! [[String:AnyObject]])[index]["history"] = history
userDict["accounts"][index]["history"] = history
userDict["accounts"][index]["history"]! = history
}
All four lines inside of setHistory try to do the same thing, and all fail.
Right now the way you are doing this:
userDict["accounts"] as! [[String:AnyObject]])[index]["history"]
you are working with an immutable container.
You are going to have to design it like this:
func setHistory(index: Int, history: [String]) {
//this line copies from user dict, it is not a pointer
var account = userDict["accounts"] as! [[String:AnyObject]];
//this line sets the new history
account[index]["history"] = history;
//this line will update the dictionary with the new data
userDict["accounts"] = account
}
I think you are better off with a class to model your data.
Anyhow, you can call an old friend from ObjC, NSMutableDictionary:
var userDict = [String: AnyObject]()
var accounts = [NSMutableDictionary]()
accounts.append(["history": ["history1.1", "history1.2"]])
accounts.append(["history": ["history2.1", "history2.2"]])
userDict["accounts"] = accounts
func setHistory(index: Int, history: [String]) {
userDict["accounts"]![index].setObject(history, forKey: "history")
}
setHistory(0, history: ["history1.1", "history1.2", "history1.3"])
print(userDict)
I am new to Swift.
I am trying to get some data from a webservice and to loop the JSON data to make a simple array.
DataManager.getDataFromEndpoint{ (endpointData) -> Void in
let json = JSON(data: endpointData)
if let programsOnAir = json["data"]["data"]["on_air"].array{
var onAirArray = []
for onAir in programsOnAir {
var eventName = onAir["event_name"].string
var eventCover = onAir["event_cover"].string
var tuple = (name: eventName!, cover: eventCover!)
onAirArray.insert(tuple, atIndex: 1)
}
println(onAirArray)
}
}
I get an error where the member .insert does not exist
BUt if I init the array like this var onAirArray = [name: "something, cover: "somethingelse"] then it works.
I need to work with empty arrays and I need to be them mutable, because I have no idea what I may get from the JSON given by the API endpoint.
What am I doing wrong?
The problem is with this line:
var onAirArray = []
Since you haven't given the array an explicit type, this is creating a new instance of NSArray, which doesn't have a method called insert. Which is why this is probably the exact error message you're receiving.
'NSArray' does not have a member named 'insert'
To fix this, explicitly state the type of your array.
var onAirArray: [(String, String)] = []