var QuestionID = [String]()
var Questions = [String]()
var AnswersID = [[String]]()
var AnswersArray = [[String]]()
var AnswerType = [String]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell{
let cell =
tblQuickQuestions.dequeueReusableCell(withIdentifier:
"idQuickQuestionsTableViewCell", for: indexPath) as!
QuickQuestionsTableViewCell
cell.backgroundColor = UIColor.white
cell.selectionStyle = .none
cell.lblRadio!.text = AnswersArray[indexPath.sections]
[indexPath.rows]
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int{
return AnswersArray[section].count
}
/*********************************************************************************************/
My Array Values:
Questions ID: ["2", "3", "4", "5", "6"]
Question: ["How is the flooring?", "Test Question ???", "what is ur bdate", "Test Question", "How are you ...?"]
Answer Type: ["Checkbox", "Checkbox", "Drop Down Menu", "Drop Down Menu", "Radio Buttons"]
Answers ID: [["3"], ["5"], ["6", "7", "8"], ["9"], ["10", "11", "12"]]
AnswersArray: [["test"], ["ans"], ["2 April", "7 jan", "15aug"], ["lklklk"], ["aa", "bb", "cc"]]
I want to implement an Question, Answers Quiz in which Answers are of multiple choice and can be of type Radio Buttons, Checkboxes or Lists. I have implemented Two dimensional array for answers like: Answers[["1","2","3"],["1"],["1","2","3","4","5"]]. where First inner array represents answers for first question, second inner array for second question and so on. and for Questions like: Questions["Question1","Question2","Question3"]. Now I want to assign these values to label present in table view cell and wants to display next Question and answers on next button click.
You can solve this problem by creating Singleton array of Dictionary.
Suppose my singleton array name is 'MainArray'.
So i have created one function which will be called from viewDidLoad() function.
func gatherData(){
MainArray.removeAll(keepingCapacity: false)
let QuestionsID : [String] = ["2", "3", "4", "5", "6"]
let Question : [String] = ["How is the flooring?", "Test Question ???", "what is ur bdate", "Test Question", "How are you ...?"]
let AnswerType : [String] = ["Checkbox", "Checkbox", "Drop Down Menu", "Drop Down Menu", "Radio Buttons"]
// let AnswersID : [[String]] = [["3"], ["5"], ["6", "7", "8"], ["9"], ["10", "11", "12"]]
let AnswersArray : [[String]] = [["test"], ["ans"], ["2 April", "7 jan", "15aug"], ["lklklk"], ["aa", "bb", "cc"]]
var emptyDictionary = [String: Any]()
for ind in 0...QuestionsID.count-1{
emptyDictionary["QID"] = QuestionsID[ind]
emptyDictionary["QNAME"] = Question[ind]
emptyDictionary["ANSWERTYPE"] = AnswerType[ind]
var innerArray : [String] = []
for inner in 0...AnswersArray.count-1{
innerArray = [AnswersArray[ind][inner]]
break
}
emptyDictionary["ANSWERARRAY"] = innerArray
emptyDictionary["ANSWER_USER"] = ""
MainArray.append(emptyDictionary)
}
print("MainArray:\(MainArray)")
}
Output from console:
MainArray:[["ANSWERARRAY": ["test"], "ANSWER_USER": "", "ANSWERTYPE": "Checkbox", "QNAME": "How is the flooring?", "QID": "2"], ["ANSWERARRAY": ["ans"], "ANSWER_USER": "", "ANSWERTYPE": "Checkbox", "QNAME": "Test Question ???", "QID": "3"], ["ANSWERARRAY": ["2 April"], "ANSWER_USER": "", "ANSWERTYPE": "Drop Down Menu", "QNAME": "what is ur bdate", "QID": "4"], ["ANSWERARRAY": ["lklklk"], "ANSWER_USER": "", "ANSWERTYPE": "Drop Down Menu", "QNAME": "Test Question", "QID": "5"], ["ANSWERARRAY": ["aa"], "ANSWER_USER": "", "ANSWERTYPE": "Radio Buttons", "QNAME": "How are you ...?", "QID": "6"]]
By using MainArray index position you can switch between array values which is nothing but single dictionary for that index, and you can display results as per the data in dictionary.
If this solves your problem, don't forget to accept the answer.
Related
This question already has answers here:
Sorting array alphabetically with number
(8 answers)
Closed 5 years ago.
I have an array of strings,
let array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
I would like to get the output sorted in ascending as,
let sorted = [ "1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA" ]
I tried using the sorted command but it does not work when it encounters more than 2 digits e.g.: 100, 101, 200 etc.
array.sorted { $0? < $1? }
What would be the simple way to get this?
Xcode 11.3 • Swift 5.2 or later
You can use String method localizedStandardCompare (diacritics and case insensitive):
let array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
let sorted = array.sorted {$0.localizedStandardCompare($1) == .orderedAscending}
print(sorted) // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
or using the method sort(by:) on a MutableCollection:
var array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
array.sort {$0.localizedStandardCompare($1) == .orderedAscending}
print(array) // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
You can also implement your own localized standard sort method extending Collection:
public extension Sequence where Element: StringProtocol {
func localizedStandardSorted(ascending: Bool = true) -> [Element] {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sorted { $0.localizedStandardCompare($1) == result }
}
}
let array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
let sorted = array.localizedStandardSorted()
print(sorted) // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
The mutating method as well extending MutableCollection:
public extension MutableCollection where Element: StringProtocol, Self: RandomAccessCollection {
mutating func localizedStandardSort(ascending: Bool = true) {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sort { $0.localizedStandardCompare($1) == result }
}
}
var array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
array.localizedStandardSort()
print(array) // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
If you need to sort your array numerically you can use String compare method setting the options parameter to .numeric:
public extension Sequence where Element: StringProtocol {
func sortedNumerically(ascending: Bool = true) -> [Element] {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sorted { $0.compare($1, options: .numeric) == result }
}
}
public extension MutableCollection where Element: StringProtocol, Self: RandomAccessCollection {
mutating func sortNumerically(ascending: Bool = true) {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sort { $0.compare($1, options: .numeric) == result }
}
}
var numbers = ["1.5","0.5","1"]
let sortedNumbers = numbers.sortedNumerically()
print(sortedNumbers) // ["0.5", "1", "1.5"]
print(numbers) // ["1.5","0.5","1"]
// mutating the original collection
numbers.sortNumerically(ascending: false)
print(numbers) // "["1.5", "1", "0.5"]\n"
To sort a custom class/structure by one of its properties:
extension MutableCollection where Self: RandomAccessCollection {
public mutating func localizedStandardSort<T: StringProtocol>(_ predicate: (Element) -> T, ascending: Bool = true) {
sort {
predicate($0).localizedStandardCompare(predicate($1)) ==
(ascending ? .orderedAscending : .orderedDescending)
}
}
}
public extension Sequence {
func localizedStandardSorted<T: StringProtocol>(_ predicate: (Element) -> T, ascending: Bool = true) -> [Element] {
sorted {
predicate($0).localizedStandardCompare(predicate($1)) ==
(ascending ? .orderedAscending : .orderedDescending)
}
}
}
public extension Sequence {
func sortedNumerically<T: StringProtocol>(_ predicate: (Element) -> T, ascending: Bool = true) -> [Element] {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sorted { predicate($0).compare(predicate($1), options: .numeric) == result }
}
}
public extension MutableCollection where Element: StringProtocol, Self: RandomAccessCollection {
mutating func sortNumerically<T: StringProtocol>(_ predicate: (Element) -> T, ascending: Bool = true) {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sort { predicate($0).compare(predicate($1), options: .numeric) == result }
}
}
Playground testing
struct Person {
let name: String
let age : Int
}
extension Person : CustomStringConvertible {
var description: String { "name: \(name), age: \(age)" }
}
var people: [Person] = [.init(name: "Éd Sheeran", age: 26),
.init(name: "phil Collins", age: 66),
.init(name: "Shakira", age: 40),
.init(name: "rihanna", age: 25),
.init(name: "Bono", age: 57)]
let sorted = people.localizedStandardSorted(\.name)
print(sorted) // [name: Bono, age: 57, name: Éd Sheeran, age: 26, name: phil Collins, age: 66, name: rihanna, age: 25, name: Shakira, age: 40]
edit/update: Xcode 12 • Swift 5.5 or later
You can use KeyPathComparator and pass localizedStandard as the Comparator:
people.sort(using: KeyPathComparator(\.name, comparator: .localizedStandard))
print(people) // [name: Bono, age: 57, name: Éd Sheeran, age: 26, name: phil Collins, age: 66, name: rihanna, age: 25, name: Shakira, age: 40]
people.sort(using: KeyPathComparator(\.name, comparator: .localizedStandard, order: .reverse))
print(people) // "[name: Shakira, age: 40, name: rihanna, age: 25, name: phil Collins, age: 66, name: Éd Sheeran, age: 26, name: Bono, age: 57]"
For sorting just an array of strings you can also use KeyPathComparator and pass self for the KeyPath:
var array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
array.sort(using: KeyPathComparator(\.self, comparator: .localizedStandard))
array // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
array.sort(using: KeyPathComparator(\.self, comparator: .localizedStandard, order: .reverse))
array // ["NA", "NA", "210", "200", "101", "100", "20", "10", "7", "1"]
I want to get Addresses from profile dictionary,but I got the error "type any? has no subscript members"
var address:[[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
var profile:[String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
profile["Addresses"][0] <-----------------type any? has no subscript members
How can I fix it and get the address? Thanks a lot.
When you subscript profile with "Addresses", you're getting an Any instance back. Your choice to use Any to fit various types within the same array has caused type erasure to occur. You'll need to cast the result back to its real type, [[String: Any]] so that it knows that the Any instance represents an Array. Then you'll be able to subscript it:
func f() {
let address: [[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
let profile: [String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
guard let addresses = profile["Addresses"] as? [[String: Any]] else {
// Either profile["Addresses"] is nil, or it's not a [[String: Any]]
// Handle error here
return
}
print(addresses[0])
}
This is very clunky though, and it's not a very appropriate case to be using Dictionaries in the first place.
In such a situation, where you have dictionaries with a fixed set of keys, structs are a more more appropriate choice. They're strongly typed, so you don't have to do casting up and down from Any, they have better performance, and they're much easier to work with. Try this:
struct Address {
let address: String
let city: String
let zip: Int
}
struct Profile {
let name: String
let age: Int
let addresses: [Address]
}
let addresses = [
Address(
address: "someLocation"
city: "ABC"
zip: 123
),
Address(
address: "someLocation"
city: "DEF"
zip: 456
),
]
let profile = Profile(name: "Mir", age: 10, addresses: addresses)
print(profile.addresses[0]) //much cleaner/easier!
You should re-think how you've chosen to construct adress and profile; see e.g. Alexander Momchliov's answer.
For the technical discussion, you could extract the Any members of profile that you know to contain [String: Any] dictionaries wrapped in an Any array; by sequential attempted type conversion of profile["Addresses"] to [Any] followed by element by element (attempted) conversion to [String: Any]:
if let adressDictsWrapped = profile["Addresses"] as? [Any] {
let adressDicts = adressDictsWrapped.flatMap{ $0 as? [String: Any] }
print(adressDicts[0]) // ["Zip": 123, "City": "ABC", "Address": "someLocation"]
print(adressDicts[1]) // ["Zip": 456, "City": "DEF", "Address": "someLocation"]
}
or, without an intermediate step ...
if let adressDicts = profile["Addresses"] as? [[String: Any]] {
print(adressDicts[0]) // ["Zip": 123, "City": "ABC", "Address": "someLocation"]
print(adressDicts[1]) // ["Zip": 456, "City": "DEF", "Address": "someLocation"]
}
But this is just a small lesson in attempted typed conversion (-> don't do this).
I agree that if you rethink your design as suggested earlier. For discussion sake you can perform the following to achieve what you are seeking.
var address:[[String : Any]] = [["Address": "someLocation", "City": "ABC","Zip" : 123],["Address": "someLocation", "City": "DEF","Zip" : 456]]
var profile:[String : Any] = ["Name": "Mir", "Age": 10, "Addresses": address]
if let allAddresses = profile["Addresses"] as? [[String:Any]] {
print("This are all the address \(allAddresses[0])")
}
How I can remove a dict from an array of dictionaries?
I have an array of dictionaries like so: var posts = [[String:String]]() - and I would like to remove a dictionary with a specific key, how would I proceed? I know that I can remove a value from a standard array by doing Array.removeAtIndex(_:) or a dictionary key by doing key.removeValue(), but an array of dictionaries is more tricky.
Thanks in advance!
If I understood you questions correctly, this should work
var posts: [[String:String]] = [
["a": "1", "b": "2"],
["x": "3", "y": "4"],
["a": "5", "y": "6"]
]
for (index, var post) in posts.enumerate() {
post.removeValueForKey("a")
posts[index] = post
}
/*
This will posts = [
["b": "2"],
["y": "4", "x": "3"],
["y": "6"]
]
*/
Since both your dictionary and the wrapping array are value types just modifying the post inside of the loop would modify a copy of dictionary (we created it by declaring it using var), so to conclude we need to set the value at index to the newly modified version of the dictionary
Removing all Dictionaries with a given key
let input = [
[
"Key 1" : "Value 1",
"Key 2" : "Value 2",
],
[
"Key 1" : "Value 1",
"Key 2" : "Value 2",
],
[
"Key 1" : "Value 1",
"Key 2" : "Value 2",
"Key 3" : "Value 3",
],
]
let keyToRemove = "Key 3"
//keep dicts only if their value for keyToRemove is nil (meaning key doesn't exist)
let result = input.filter{ $0[keyToRemove] == nil }
print("Input:\n")
dump(input)
print("\n\nAfter removing all dicts which have the key \"\(keyToRemove)\":\n")
dump(result)
You can see this code in action here.
Removing the only the first Dictionary with a given key
var result = input
//keep dicts only if their value for keyToRemove is nil (meaning key doesn't exist)
for (index, dict) in result.enumerate() {
if (dict[keyToRemove] != nil) { result.removeAtIndex(index) }
}
print("Input:\n")
dump(input)
print("\n\nAfter removing all dicts which have the key \"\(keyToRemove)\":\n")
dump(result)
You can see this code in action here.
I want to save the subcategory data in this form [[value1,value2,...],[value1, value2],[value1],.....] in the following code
var subcategories = [SubCategory]()
for (_, item) in json {
//do something with item.id, item.name
for (_, subcategory) in item["subcategory"] {
let subcategory = SubCategory(
id: Int(subcategory ["id"].stringValue),
name: subcategory ["name"].string,
desc: subcategory ["desc"].string,
image: subcategory ["image"].string,
coupon: Int(subcategory ["coupon"].stringValue),
icon: subcategory ["icon"].string,
order: Int(subcategory ["order"].stringValue),
aname: subcategory ["aname"].string,
options: Int(subcategory ["options"].stringValue),
items: subcategory ["items"].arrayObject
)
subcategories.append(subcategory)
}
print(subcategories.count)
for sub in subcategories {
print(sub.name)
print(sub.id)
print(sub.desc)
self.SUBCATNAME.append(sub.name!)
self.SUBARRAY?.append(self.SUBCATNAME)
}
print(self.SUBCATNAME)
print(self.SUBARRAY)
}
I need to append all the subcategory name in an array of dictionary like the above structure. Here i created SUBARRAY as var SUBARRAY:[[String]] = []. but the value is coming as nil. Here i am getting the json data from Api using Swiftyjson. How to implement this??
my sample json data is as below:
like wise so many subcategories are there
[
{
"id": "244",
"name": "PIZZAS",
"subcategory": [
{
"id": "515",
"name": "MARGARITA",
"description": "Cheese and Tomato",
"image": "",
"icon": "",
"coupon": "1",
"order": "1",
"aname": "",
"options": "2"
},
{
"id": "516",
"name": "ABC",
"description": "HNDDSGHFD",
"image": "",
"icon": "",
"coupon": "1",
"order": "1",
"aname": "",
"options": "2",
},
{
"id": "516",
"name": "DEF",
"description": "HFDGFJJFHFKH",
"image": "",
"icon": "",
"coupon": "1",
"order": "1",
"aname": "",
"options": "2",
}
]
},
{
......
}
]
if you try this code
for (NSDictionary *dictionary in ArrCategory)
{
NSMutableArray *sub_cat_data=[dictionary objectForKey:#"sub_cat_data"];
for (NSDictionary *sub_cat_dict in sub_cat_data)
{
NSMutableArray *sub_cat_data=[sub_cat_dict objectForKey:#"sub_data"];
for (NSDictionary *dictionary1 in sub_cat_data)
{
NSMutableDictionary *Dic_Sub_cat=[[NSMutableDictionary alloc]init];
NSString *str_dic_id=[dictionary1 objectForKey:#"sub_id"];
NSString *str_dic_name=[dictionary1 objectForKey:#"sub_name"];
[Dic_Sub_cat setObject:str_dic_id forKey:#"sub_id"];
[Dic_Sub_cat setObject:str_dic_name forKey:#"sub_name"];
[Dic_Sub_cat setObject:#"0" forKey:#"sub_Chekid"];
[New_ArrCategory addObject:Dic_Sub_cat];
}
}
}
swift example
if let results: NSMutableArray = jsonResult["data"] as? NSMutableArray
{
var ArrMoodtype2 : NSMutableArray!
ArrMoodtype2 = NSMutableArray()
ArrMoodtype2 = results
ArrFeel = NSMutableArray()
for var i = 0; i < ArrMoodtype2.count; i++
{
var Dic : NSMutableDictionary!
Dic = NSMutableDictionary()
let tempDic: NSMutableDictionary = ArrMoodtype2[i] as! NSMutableDictionary
let strMoodCatID = tempDic ["mood_cat_id"] as! String
let strMoodID = tempDic ["mood_id"] as! String
let strMoodImage = tempDic ["mood_image"] as! String
let strMoodName = tempDic ["mood_name"] as! String
Dic.setObject(strMoodCatID, forKey: "mood_cat_id")
Dic.setObject(strMoodID, forKey: "mood_id")
Dic.setObject(strMoodImage, forKey: "mood_image")
Dic.setObject(strMoodName, forKey: "mood_name")
ArrFeel.addObject(Dic)
}
}
I am trying to fetch the Json data from Api which is in the following format
[
{
"id": "244",
"name": "PIZZAS",
"image": "",
"coupon": "1",
"icon": "",
"order": "1",
"aname": "",
"options": "2",
"subcategory": [
{
"id": "515",
"name": "MARGARITA",
"description": "Cheese and Tomato",
"image": "",
"icon": "",
"coupon": "1",
"order": "1",
"aname": "",
"options": "2",
"item": [
{
"id": "1749",
"name": "9 Inch Thin & Crispy Margarita",
"description": "",
"price": "3.40",
"coupon": "1",
"image": "",
"options": "2",
"order": "1",
"addon": "495",
"aname": "",
"icon": ""
},
{
"id": "1750",
"name": "12 Inch Thin & Crispy Margarita",
"description": "",
"price": "5.20",
"coupon": "1",
"image": "",
"options": "2",
"order": "2",
"addon": "496",
"aname": "",
"icon": ""
}
]
}
How can i fetch the "subcategory name" as well as " items name". Please help me out.I have written some codes and tried to fetch but not working.
var json: NSArray!
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions()) as? NSArray
} catch {
print(error)
}
self.AllData = json.valueForKey("subcategory") as! Array<String>
print(self.AllData)
print(self.AllData.count)
But its not fetching any value
Other way also I have tried but still no data fetching . only the data is coming in json1.
do {
let json1 = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions())
// print(json1)
if let subcategory = json1["subcategory"] as? [[String: AnyObject]] {
for subname in subcategory {
if let name = subname["name"] as? String {
print(name)
}
if let items = subname["item"] as? [[String: AnyObject]] {
for item in items {
if let itemName = item["name"] as? String {
print(itemName)
}
}
}
}
}
} catch {
print(error)
}
At first its an array of objects/Dictionary.And you are creating an array of string. Thats why for subcategory it will not work.You need to create an array of Dictionaries like this:
do {
let json1 = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions())
self.AllData = json1.valueForKey("name") as! Array<String>
print(self.AllData)
print("Number of menu = \(json1.count)")
for var i in 0..<json1.count {
print(" \n \(i+1) row menu \n")
if let subs = json1[i]["subcategory"] as? [[String: AnyObject]] {
//print(subs)
for sub in subs {
if let name = sub["name"] as? String {
print("subcategory name= \t \(name)")
//print(name)
}
if let desc = sub["description"] as? String {
print("description= \t \(desc)")
// print(desc)
}
}
print("Number of subcategory= \(subs.count)")
for var i in 0..<subs.count {
if let items = subs[i]["item"] as? [[String: AnyObject]] {
print("items = ")
print(items.count)
for item in items {
if let itemName = item["name"] as? String {
print(itemName)
}
}
}
}
}
}
}catch {
print(error)
}
Try this one it will work accoording to your json data
This may just be a problem when cutting and pasting into the question, but it looks like your JSON data isn't formatted correctly (the []s and {}s don't match up). As the previous commentor said, you're dealing with an array of dictionaries not an array of strings. Try something like this:
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions())
if let subs = json[0]["subcategory"] as? [[String: AnyObject]] {
for sub in subs {
if let name = sub["name"] as? String {
print(name)
}
if let items = sub["item"] as? [[String: AnyObject]] {
for item in items {
if let itemName = item["name"] as? String {
print(itemName)
}
}
}
}
}
} catch {
print(error)
}