how to filter swiftyjson array - ios

I'll try every solution which I get from stack overflow but its my bad luck. I store my JSON response in [Any] array like this:
var json = JSON()
var arrClientType = [Any]()
self.json = JSON(value) //value is json data
self.arrClientType = self.json["client_type_data"].arrayValue
now, I want to filter this array and reload that filtered data in tableview.
[{
"client_type_name" : "Asset Manager",
"client_type_id" : 1
}, {
"client_type_name" : "Broker Dealer",
"client_type_id" : 5
}, {
"client_type_name" : "Corporate",
"client_type_id" : 8
}, {
"client_type_name" : "Custodian and Prime Broker",
"client_type_id" : 3
}, {
"client_type_name" : "Diversified Financial Services Firms",
"client_type_id" : 4
}, {
"client_type_name" : "Fund Administrator",
"client_type_id" : 6
}, {
"client_type_name" : "Hedge Fund Manager",
"client_type_id" : 2
}, {
"client_type_name" : "Individual",
"client_type_id" : 7
}]
I'll try this also :
let filtered = JSON(self.arrList).arrayValue.filter({
$0["client_type_name"].arrayValue.map({ $0.stringValue }).contains("Broker Dealer")
})
print ("filterdData: \(filtered)")
but it give me entry filter array.
Please help me.

try this
filtered = arrList.filter { $0["client_type_name"].stringValue.contains("Broker Dealer") }
and change your self.arrlist to array of dictiony type
var arrList: [JSON] = []
var filtered :[JSON] = []

Try this one , you will be able to filtered the data which contain the "client_type_name" as a Broker Dealer.
let arrClientType = [["client_type_name":"Asset Manager" , "client_type_id":1] , ["client_type_name":"Broker Dealer" , "client_type_id":5] , ["client_type_name":"Corporate" , "client_type_id":8]]
if let filteredData = arrClientType.filter({(($0 as? [String:Any])?["client_type_name"] as? String ?? "") == "Broker Dealer"}) as? [Any] {
print(filteredData)
}
The filteredData is the arrayOfDictionary which contain the dictionaries in which "client_type_name" as a Broker Dealer.

Related

How to get one value from a Codable struct with multiple values?

I have a large JSON response and inside
{
"availabilityResultList": [
{
"availabilityRouteList": [
{
"availabilityByDateList": [
{
"originDestinationOptionList": [
there are 3 separate
"originDestinationOptionList": [
{
"fareComponentGroupList":[...]
},
{
"fareComponentGroupList":[...]
},
{
"fareComponentGroupList":[...]
},
],
I can access the values in the first 'fareComponentGroupList' with Codables
as
root.availabilityResultList.first?.availabilityRouteList.first?.availabilityByDateList.first?.originDestinationOptionList.first?.fareComponentGroupList.first?.xxx
How do I access values the second and third fareComponentGroupList ?
(I am sorry about these silly questions but I am new with swift Codables)
Since originDestinationOptionList returns an array of dictionary, just fetch it from there by index.
let originDestinationOptionList = root.availabilityResultList.first?.availabilityRouteList.first?.availabilityByDateList.first?.originDestinationOptionList
let firstobject = originDestinationOptionList[0]["fareComponentGroupList"]
let secondObject = originDestinationOptionList[1]["fareComponentGroupList"]
let firstObjectsFirstItem = firstObject[0]
If the above gives error, this works ( Swift 5)
let originDestinationOptionList = root.availabilityResultList.first?.availabilityRouteList.first?.availabilityByDateList.first?.originDestinationOptionList
let firstobject = originDestinationOptionList[0].fareComponentGroupList.first
let firstObjectsFirstItem = firstObject?. (add the remaining part)

how to get value from response in swift which returns [String:AnyObject] Swift4

in my Api call i getting response in [String : AnyObject] format from this i need to get few elements and store it on Array how to achieve this in Swift4 here my sample response could help how to get values from my response
My Sample Response :
["result": valid: (
{
id = 1;
"name" = "Alen"
},
{
id = 12;
"name" = "Peter"
},
{
id = 14;
"name" = "John"
},
{
id = 16;
"name" = "Ema"
},
{
id = 19;
"name" = "Shane"
},
{
id = 211;
"name" = "Mia"
}
)]
From this response i need to get all "name" values in array how to acheive this in swift 4
You can use swiftyJSON for seperate "name" from the response
let jsonData = JSON(data : data)
data - response of your api
then use forloop for adding name data in array
Hope so, this will help you.
struct Details{
let Name : String
}
And where you are getting result from server, use this code and after that your name values will be in Result Array.
var RecordsArr = [Details]()
let Result = recordJSON.value(forKey: "result") as? [NSDictionary]
for item in Result {
let id_records = Details(Name: item[“name”]! as! String)
RecordsArr.append(id_records)
}
Let me tell, if you have any problem.

Adding to dictionary dynamically

I 'm having an array of dictionary like so...
[
{
"id" : "3",
"sellingPrice" : "520",
"quantity" : "15"
},
{
"id" : "5",
"sellingPrice" : "499",
"quantity" : "-1"
},
{
"id" : "8",
"sellingPrice" : "500",
"quantity" : "79"
}
]
Now I want to add to the dictionary another key called remaining_balance with a value of 420,499 & 500 respectively. How can I achieve this..? Hope somebody can help...
It seems like you want to add a value to your dictionary that is an array:
var arrDict = Array<Dictionary<String,Any>>() //Your array
arrDict.append(["id":"3","sellingPrice":"520","quantity":"13"])
arrDict.append(["id":"5","sellingPrice":"43","quantity":"32"])
arrDict.append(["id":"8","sellingPrice":"43","quantity":"33"])
let arrValue = ["420","499","500"] //Your remaining value in array
print("Before ",arrDict)
for (index,dict) in arrDict.enumerated() {
var dictCopy = dict //assign to var variable
dictCopy["remaining_balance"] = arrValue[index]
arrDict[index] = dictCopy //Replace at index with new dictionary
}
print("After ",arrDict)
EDIT
If you are able keep an index of an array it would be possible,
Assuming that you have the index of an array
var dictCopy = arrDict[index]
dictCopy["remaining_balance"] = "666" //Your calculated value
arrDict[index] = dictCopy //Replace at index with new dictionary
var newKV = [["remaining_balance": "420"],["remaining_balance": "490"],["remaining_balance": "500"]]
let array = [["id":"3", "sellingPrice":"520", "quantity":"15"], ["id":"5", "sellingPrice":"520", "quantity":"15"], ["id":"8", "sellingPrice":"520", "quantity":"15"]]
let newArray = array.enumerated().map { (index : Int, value: [String: String]) -> [String: String] in
var dic = value
dic.merge(newKV[index]) { (_, new) -> String in
new
}
return dic
}
You could achieve it by mapping your array:
var myArray = [["id": "3", "sellingPrice": "520", "quantity" : "15"], ["id": "5", "sellingPrice": "499", "quantity" : "-1"], ["id": "8", "sellingPrice": "500", "quantity" : "79"]]
print(myArray)
/*
[["id": "3", "sellingPrice": "520", "quantity": "15"],
["id": "5", "sellingPrice": "499", "quantity": "-1"],
["id": "8", "sellingPrice": "500", "quantity": "79"]]
*/
print("___________________")
var remainingBalanceDesriedValue = 420
myArray = myArray.map { (dict: [String: String]) -> [String: String] in
var copyDict = dict
copyDict["remaining_balance"] = "\(remainingBalanceDesriedValue)"
remainingBalanceDesriedValue = (remainingBalanceDesriedValue == 420) ? 499 : (remainingBalanceDesriedValue == 499) ? 500 : 420
return copyDict
}
print(myArray)
/*
[["sellingPrice": "520", "quantity": "15", "id": "3", "remaining_balance": "420"],
["sellingPrice": "499", "quantity": "-1", "id": "5", "remaining_balance": "499"],
["sellingPrice": "500", "quantity": "79", "id": "8", "remaining_balance": "500"]]
*/
Let's assume you have an array of dictionaries like so:
var arrayOfDictionaries = [
[
"id": 3,
"sellingPrice": 520,
"quantity": 15
]
]
It is important that arrayOfDictionaries is not a let constant, otherwise it is considered immutable and you can not call append on it.
Now you init a new dictionary like:
let newDictionary = [
"id": 10,
"remaining_balance": 420,
"quantity": 15
]
Now add the newDictionary like
arrayOfDictionaries.append(newDictionary)
If the order is important
If the order is important there are a couple of ways to go about that.
When calling append the new value (in this case the new dictionary) will always be inserted at the bottom of the array.
If for some reason you can not call append in the correct order you could use insert, which inserts your dictionary at a specific position.
Yet another way is to append the values wildly and after you are done, call sort on the array.
Improvement Tips
Notice that for the values I did not use strings, as you only have numbers like "id" : 30.
Also, if you want the second key to be called remaining_balance you should call the first key selling_price instead of sellingPrice. Because of conistency.
Alternative approach
As far as I have understood you are trying to implement some software that is responsibly for selling some products.
I think you are tackling this problem from a completely wrong side.
I think you should read about database relationships. Selling products actually is a very common problem.
Maybe this will help you. I would offer a possible solution myself, but I think this misses the point of your question.
If you decide to use the database approach, you won't necessarily have to use a database. You can take the approach and implement it using simple structs/classes/arrays.
I noticed this question lacks an extension answer, yes.. I'm gonna be that guy, so here it is. This could be made more generic by supporting other types of dictionaries, feel free to pitch in ;)
Inspiration from #eason's answer.
var newKV = [["remaining_balance": "420"],["remaining_balance": "490"],["remaining_balance": "500"]]
var array = [["id":"3", "sellingPrice":"520", "quantity":"15"], ["id":"5", "sellingPrice":"520", "quantity":"15"], ["id":"8", "sellingPrice":"520", "quantity":"15"]]
extension Array where Element == [String: String] {
enum UniquingKeysStrategy {
case old
case new
}
mutating func merge(with target: Array<Element>, uniquingKeysWith: UniquingKeysStrategy = .new) {
self = self.merged(with: target)
}
func merged(with target: Array<Element>, uniquingKeysWith strategy: UniquingKeysStrategy = .new) -> Array<Element> {
let base = self.count > target.count ? self : target
let data = self.count > target.count ? target : self
return data.enumerated().reduce(into: base, {
result, data in
result[data.offset]
.merge(data.element, uniquingKeysWith: {
old, new in
if strategy == .new { return new }
return old
})
})
}
}
let mergedArrays = newKV.merged(with: array, uniquingKeysWith: .old)
array.merge(with: newKV)
Happy Coding :)

Firebase looping multi level nodes

I am trying to get results from a node that has one more level of nodes and cannot get through it:
I am retrieving the data like this (it works perfectly but not for the node called "items"):
func fetchMeals() {
print("start pulling data")
let user = Auth.auth().currentUser?.uid
ref.child("Users_Food_Data").child(user!).queryOrderedByKey().observeSingleEvent(of: .value, with: { snapshot in
if snapshot.value as? [String : AnyObject] != nil {
let allMeals = snapshot.value as! [String : AnyObject]
self.foodArray.removeAll()
for (_, value) in allMeals {
let foodToShow = FoodStruct()
if let calories = value["calories"] as? String,
let itemCarbs = value["energy"] as? String,
let itemProteins = value["proteins"] as? String,
let itemFat = value["fat"] as? String,
let date = value["date"] as? String,
let id = value["id"] as? String,
let name = value["name"] as? String,
let interval = value["interval"] as? Int {
foodToShow.itemKcal = calories
foodToShow.itemCarbs = itemCarbs
foodToShow.itemProteins = itemProteins
foodToShow.itemFat = itemFat
foodToShow.id = id
foodToShow.interval = interval
foodToShow.date = date
foodToShow.itemName = name
self.foodArray.append(foodToShow)
self.collectionView?.reloadData()
}
self.breakfastArray.sort(by: {$0.interval! > $1.interval!})
}
}
})
}
And the database looks like this:
"Users_Food_Data" : {
"JztkBihGgda0jtSpe6pNwt8hZu13" : {
"Breakfast:23 Sep 2017" : {
"calories" : "1145.0",
"date" : "23 Sep 2017",
"energy" : "238.8",
"fat" : "3.0",
"id" : "-Kukx_9lSpCh3lcEMzap",
"interval" : 1.506207565807117E9,
"items" : {
"-KukxKAntXDaS__v3ZLA" : {
"calories" : "30",
"date" : "23 Sep 2017",
"energy" : "6",
"fat" : "0.1",
"interval" : 1.506207500336909E9,
"itemKey" : "-KukxKAntXDaS__v3ZLA",
"mealKey" : "-KukxKAntXDaS__v3ZLB",
"name" : "Strawberries",
"proteins" : "0.8",
"quantity" : "3"
},
"-KukxLYmyg32lU1D3Wh3" : {
"calories" : "29",
"date" : "23 Sep 2017",
"energy" : "9",
"fat" : "0.5",
"interval" : 1.506207505968336E9,
"itemKey" : "-KukxLYmyg32lU1D3Wh3",
"mealKey" : "-KukxLYmyg32lU1D3Wh4",
"name" : "Lemon",
"proteins" : "1.1",
"quantity" : "1"
}
},
"name" : "Breakfast",
"proteins" : "17.0"
},
"Breakfast:24 Sep 2017" : {
"calories" : "959.0",
"date" : "24 Sep 2017",
"energy" : "106.4",
"fat" : "46.1",
"id" : "-KunWOZeSxW9eCIA6O1z",
"interval" : 1.506250519537633E9,
"items" : {
"-KulrJq6jOpsG6oiJuDM" : {
"calories" : "458",
"date" : "24 Sep 2017",
"energy" : "4.6",
"fat" : "45",
"interval" : 1.506222704055992E9,
"itemKey" : "-KulrJq6jOpsG6oiJuDM",
"mealKey" : "-KulrJq6jOpsG6oiJuDN",
"name" : "Coconut",
"proteins" : "4",
"quantity" : "1"
},
How do I do that when I know only "Users_Food_Data" and user ID. I just want to list them in the apropiate cells.
Here is my suggestion.
First looking on your database structure, you currently have something like this :
Users_Food_Data
|_userid
|_FoodStruct
|_items
|_id_1
|_data like calories, date...
|_id_2
|_data...
There is too much nodes and this kind of hierarchy doesn't respect what we call Denormalization. Remember that Firebase database is like a NoSQL database and it's a big difference compared to SQL classic databases. Here is an explanation to the best practice to denormalize your database structure : Structure your database
What i can suggest is structure your database more like this :
One node :
UsersFood
|_userid
|_breakfeast_id_1
|_breakfeast_id_2...
2nd node
Breakfeasts
|_breakfeast_id_1
|_item_id_1
|_item_id_2...
3rd node
Items
|_item_id_1
|_calories
|_date
|_energy...
Then in your code, you can :
Observe with a single event on UsersFood node all the breakfeast ids
Then with all breakfeast ids get items_id
Finally get items_id data
Hope it will help you through your code.
Edit 1 : You can also loop through a child node by using this :
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
//DO WHAT YOU NEED TO DO
}

Create a particular JSON Structure in Swift

I'm having trouble creating a specific structure in JSON with Swift. I use Swifty JSON for parsing but I can't figure out how to create one.
I have this array which is filled by Id's and quantity Ints of products in a shopping basket . I need to get the array into my JSON but I don't know how.
If you could help me with this I would be very glad :)
var productArray = Array<(id: Int,quantity: Int)>()
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": [
for product in productArray
{
"id": product.id
"quantity": product.quantity
}
]
]
You can't just start looping through stuff while defining your dictionary. Here's another approach.
First, create your array:
var productArray = Array<(id: Int,quantity: Int)>()
Add some products (for testing):
productArray += [(123, 1000)]
productArray += [(456, 50)]
Map this array into a new array of dictionaries:
let productDictArray = productArray.map { (product) -> [String : Int] in
[
"id": product.id,
"quantity": product.quantity
]
}
Use the new mapped array in your JSON object:
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": productDictArray
]
You are not supposed to do any kind of looping/condition making block of codes while creating Array's or Dictionary. For that you need to execute that piece of code outside, create a variable and use it.
Do try this way.
var productArray = Array<(id: Int,quantity: Int)>()
var prods = [[String:Int]]()
for product in productArray
{
var eachDict = [String:Int]()
eachDict["id"] = product.id
eachDict["quantity"] = product.quantity
prods.append(eachDict)
}
let jsonObject: [String: AnyObject] = [
"order": 1,
"client" : 1,
"plats": prods
]

Resources