Convert String Array to JSON or 2D Array SWIFT - ios

I currently have a NSMutableArray "localArray" and I am trying to create that into a JSON Array or a 2D Array. I get this data my creating a database and running a query using a for loop on the database.
{
Food,
Burger,
3.99,
1.25,
POP,
Crush,
1.99,
.89,
and more.
}
The reason why I am looking for a JSON or 2d Array is I want to hold the data in the localArray in such a way that I can identify by type and then do something like .valueForKey("Name") or .valurForKey("Price") and add that to my tableview's cell text label or labels.
{
{
Type Food,
Name Burger,
Price 3.99,
Cost 1.25,
},
{
Type POP,
Name Crush,
Price 1.99,
Cost .89,
},
and more
}
I have already tried JSONSerialization, but that failed and also tried 2d Array but no luck.
Any help will be highly appreciated.
This is how I Query and add the data to localArray
let queryType = data.select(ada, code, name, proof, size, case_size, price)
.filter(bevType == type)
let rows = Array(queryType)
for row in rows{
let name = row[self.name]
let type = row[self.type]
let cost = row[self.cost]
let price = row[self.price]
localArray.addObject(name)
localArray.addObject(type)
localArray.addObject(cost)
localArray.addObject(price)
}

I solved it myself by creating a dictionary.
for row in rows{
var rDict: Dictionary = [String: String]()
rDict["Name"] = row[self.name]
rDict["Type"] = row[self.type]
rDict["Cost"] = row[self.cost]
rDict["Price"] = row[self.price]
localArray.addObject(rDict)
}

If fields are always repeating in count of 4, you can try doing this:
var array = [[String: AnyObject]]()
for var i = 0 ; i < array.count ; i += 4 {
var k = 0
var dict = [String: AnyObject]
dict["Type"] = array[i + k++]
dict["Name"] = array[i + k++]
dict["Price"] = array[i + k++]
dict["Cost"] = array[i + k]
array.append(dict)
}
Then extract dictionary from this swift array and use same keys to extract data from dictionary to be used in your cell like
let dict = array[indexPath.row]
cell.title = dict["Name"]

Related

iterating through dictionary in TableView

this might be a common situation, but I was not able to figure out a way how to do it.
I have a dictionary with the stock amount for several items: dict = ["item1" : 2, "item2" : 5, "item3" : 10 ]
How can I now assign the keys and values to different labels in a tableView, using indexPath?
The logic I want to achieve:
cell.itemLabel.text = dict.[firstItemName]
cell.amountLabel.text = dict.[firstItemAmount]
A dictionary as data source can be annoying because a dictionary is unordered.
My suggestion is to map the dictionary to an array of a custom struct and sort the array by the keys
struct Model {
let name : String
let value: Int
}
let dict = ["item1" : 2, "item2" : 5, "item3" : 10 ]
let array = dict.map(Model.init).sorted{$0.name < $1.name}
Then in the table view you can write
cell.itemLabel.text = array[indexPath.row].name
You can use map function to get separate array of key and values
print(dict.map({$0.key}))
print(dict.map({$0. value}))
Try this:
cell.itemLabel.text = dict.map({$0.key})[indexPath.row]
cell.amountLabel.text = dict.map({$0.value})[indexPath.row]

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") }

App crashes within for loop in swift 3

Here I am just getting array count and using for loop but got crashed at let arr = arrayAdaptor[i] this line after completing my array count don't know why it's crashing can anyone help me how to resolve this
var arrayAdaptor = [Struct_Row_Rating]()
for i in 0...arrayAdaptor.count {
let arr = arrayAdaptor[i]
let number = arr.row
let row = number + 1
dict.updateValue("\(arr.rating)", forKey: "\(row)")
print(dict)
}
struct Struct_Row_Rating {
var row: Int
var rating: Double
init(row: Int , rating: Double) {
self.row = row
self.rating = rating
}}
The operator ... exceeds the range of the array. You have to write
for i in 0..<arrayAdaptor.count
or
for i in 0...arrayAdaptor.count - 1
Basically don't use these index based for loops in Swift at all.
Use Fast Enumeration:
for arr in arrayAdaptor {
and if you really need the index
for (index, arr) in arrayAdaptor.enumerated() {
Why you are using 0...arrayAdaptor.count range style avoid it and Simply Use enumerated() of an Array:
for (_,value) in arrayAdaptor.enumerated() {
let number = value.row
let row = number + 1
dict.updateValue("\(arr.rating)", forKey: "\(row)")
print(dict)
}
If you don't want any index to try with this:
for value in arrayAdaptor {
let number = value.row
let row = number + 1
dict.updateValue("\(arr.rating)", forKey: "\(row)")
print(dict)
}
See this
One of the options not mentioned in the answers is forEach approach.
arrayAdaptor.forEach { item in
print(item)
}
or
arrayAdaptor.forEach {
print($0) // without named parameter
}
// Your case:
arrayAdaptor.forEach { item in
let arr = item
let number = item.row
let row = number + 1
dict.updateValue("\(arr.rating)", forKey: "\(row)")
print(dict)
}
This is pretty much the same as the handy for..in mentioned in vadian's answer:
for arr in arrayAdaptor { ... }
From Swift 4 you can use One sided ranges.
i... is favored over i..< because the latter is ugly. We have to pick one, two would be redundant and likely to cause confusion over which is the "right" one. Either would be reasonable on pedantic correctness grounds – (i as Int)... includes Int.max consistent with ..., whereas a[i...] is interpreted as a[i..<a.endIndex] consistent with i..<.
Example:
var names = ["Jack", "New", "peter"]
let first = names[0...]
let second = names[..<names.count]
print(first)//prints ["Jack", "New", "peter"]
print(second)//prints ["Jack", "New", "peter"]
You can also iterate loop by 'map' function:
let _ = arrayAdaptor.map({ adaptor in
let number = adaptor.row
let row = number + 1
dict.updateValue("\(adaptor.rating)", forKey: "\(row)")
print(dict)
})

Applying filter and calculating Average on NSDictionary with JSON origin

I read some posts here and google about it, but still couldn't understand how to do a simple filter using the swift filter feature. I am new to Swift and functional programing, so forgive me if that is too basic.
I have the following JSON:
{
"-KjirKH7Bo7c5vq7ZH9N" = {
rank = 2;
placa = "xxx-0003";
uid = yNpL0uzI5LRj6etFGVgoWYEK2E52;
};
"-Kjiyi_i7FLl6dks6xKL" = {
rank = 5;
placa = "xxx-0003";
uid = yNpL0uzI5LRj6etFGVgoWYEK2E52;
};
}
I was able to create an array of the values with:
if let dict = snapshot.value as? NSDictionary{
let myArray = dict.map{$0.value} //array of values
}
Which creates this:
[{
rank = 5;
placa = "xxx-0003";
uid = yNpL0uzI5LRj6etFGVgoWYEK2E52;
}, {
rank = 2;
placa = "xxx-0003";
uid = yNpL0uzI5LRj6etFGVgoWYEK2E52;
}]
My goal now is:
Apply a filter to retrieve only items that the property "rank" is greater than 0.
After that I want to calculate the items rank average (in this example 2+5/2 = 3.5).
I have tried this:
myArray.filter{$0.rank > 0 }
But it fails with "Value of type 'Any' has no member 'rank'"
Any idea how I can filter this array?
I have tried with NSPredicate, but I am wondering if there is some way to take advantage of the native filter.
Looks like you have two issues:
myArray's items are of type Any and in reality they are dictionaries so you have to help compiler to understand that. Here is how to do it:
let myArray: [[String: Any]] = dict.map{ $0.value }
Because myArray contains dictionaries, you have to modify accessing values in filter:
myArray.filter{ (($0["rank"] as? Int) ?? 0) > 0 }
Hope it helps!
myArray.filter{ ((($0 as! NSDictionary)["rank"] as? Int) ?? 0) > 0 }
appending the answer of K.K Cast $0 to NSDictionary. I hope that will work

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