Map value in particular key in array of dictionary - ios

Map value the particular key wherever presents in array of dictionary and replace it in same array.
We need to update pan_card key 0 to 1, in occurence of array of dictionary.
let keyToUpdate = "pan_card"
var arrayOfDictionary = [[String:Any]]()
var firstDict = [String:Any]()
firstDict["passport"] = 0
firstDict["ration_card"] = 0
firstDict["pan_card"] = 0
var arrayDict = [String : Any]()
arrayDict["currentObject"] = firstDict
arrayDict["title"] = "Documents list"
var secondDict = [String:Any]()
secondDict["dl"] = 0
secondDict["voter"] = 0
secondDict["pan_card"] = 0
//let dic = secondDict.filter({ $0.value as! NSNumber != 0})
//secondDict = dic
//print(secondDict)
//let dictionary = ["foo": 1, "bar": 2, "baz": 5]
//
//let newDictionary = dictionary.mapValues { value in
// return value - value
//}
//print(dictionary)
//print(newDictionary)
var arrayDict2 = [String : Any]()
arrayDict2["currentObject"] = secondDict
arrayDict2["title"] = "Second Documents list"
arrayOfDictionary.append(arrayDict)
arrayOfDictionary.append(arrayDict2)
//print(arrayOfDictionary)
for (index, dictionary) in arrayOfDictionary.enumerated() {
let dict = dictionary
let newDictionary = (dict["currentObject"] as![String:Any]).mapValues { value in
return 1
}
arrayOfDictionary[index] = newDictionary
}
print(arrayOfDictionary)
This code updating every key in currentObject
and tried this as well, but it adding new key
for (index, dictionary) in arrayOfDictionary.enumerated() {
var dict = dictionary
// let newDictionary = (dict["currentObject"] as![String:Any]).mapValues { value in
// return 1
// }
var newDictionary = [String: Any]()
for (key, value) in dict["currentObject"] as![String:Any] {
dict[keyToUpdate, default: value] = 1
}
arrayOfDictionary[index] = dict
}
print(arrayOfDictionary)
I need output like below
Original value
[["currentObject": ["passport": 0, "pan_card": 0, "ration_card": 0], "title": "Documents list"], ["currentObject": ["pan_card": 0, "dl": 0, "voter": 0], "title": "Second Documents list"]]
after update
[["currentObject": ["passport": 0, "pan_card": 1, "ration_card": 0], "title": "Documents list"], ["currentObject": ["pan_card": 1, "dl": 0, "voter": 0], "title": "Second Documents list"]]
Referred Document Link
We knows manually iterating and updating values, we wanted to done with higher order function.

Using a recursive method that performs the update
func update(key:String, in dict: [String:Any], with value: Any) -> [String:Any] {
var out = [String:Any]()
if let _ = dict[key] {
out = dict
out[key] = value
} else {
dict.forEach {
if let innerDict = $0.value as? [String:Any] {
out[$0.key] = update(key: key, in: innerDict, with: value)
} else {
out[$0.key] = $0.value
}
}
}
return out
}
we can use a simple map call
var original = [["currentObject": ["passport": 0, "pan_card": 0, "ration_card": 0], "title": "Documents list"], ["currentObject": ["pan_card": 0, "dl": 0, "voter": 0], "title": "Second Documents list"]]
let result = original.map{ update(key: "pan_card", in: $0, with: 1)}
The update function was based on this answer

Related

Wrong value in correct json using Swift

I'm facing this strange problem. I have to parse this json and extract "symbol","High","low" and "direction". this is the original json
[{"ID":101,"Symbol":"PKR","Bid":105.7,"Ask":106,"High":105.7,"Low":106,"Change":0,"Direction":"0","CreateDate":"04:38:26","EntityState":2,
"EntityKey":{"EntitySetName":"v_openmarketrates","EntityContainerName":"tradebizEntities",
"EntityKeyValues":[{"Key":"ID","Value":101}],
"IsTemporary":false}},
{"ID":1,"Symbol":"EUR","Bid":126.696,"Ask":127.327,"High":126.7622,"Low":126.9752,"Change":0.4192,"Direction":"0","CreateDate":"06:37:31","EntityState":2,
"EntityKey":{"EntitySetName":"v_openmarketrates","EntityContainerName":"tradebizEntities","EntityKeyValues":[{"Key":"ID","Value":1}],
"IsTemporary":false}}]
When i'm parsing this in json, it is fetching all the values correctly except the value of "Direction",like this:
[{
Ask = 106;
Bid = "105.7";
Change = 0;
CreateDate = "04:38:26";
Direction = 0;
EntityKey = {
EntityContainerName = tradebizEntities;
EntityKeyValues = (
{
Key = ID;
Value = 101;
}
);
EntitySetName = "v_openmarketrates";
IsTemporary = 0;
};
EntityState = 2;
High = "105.7";
ID = 101;
Low = 106;
Symbol = PKR;
},
{
Ask = "127.265";
Bid = "126.623";
Change = "0.3463";
CreateDate = "06:30:46";
Direction = 0;
EntityKey = {
EntityContainerName = tradebizEntities;
EntityKeyValues = (
{
Key = ID;
Value = 1;
}
);
EntitySetName = "v_openmarketrates";
IsTemporary = 0;
};
EntityState = 2;
High = "126.7306";
ID = 1;
Low = "126.9752";
Symbol = EUR;
}
i have no idea how the value inside json is getting changed while parsing even though rest of the values are correct. this is how i'm parsing it.
if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? [NSDictionary] {
print("kerb rates full json = ",jsonResult )
for field in jsonResult as? [AnyObject] ?? [] {
print("fields of kerb rates = \(field)")
print("kerb directions \((field["Direction"] as? String)!)")
let subfield : AnyObject = (field["EntityKey"] as? AnyObject)!
let sub_subfield : AnyObject = (subfield["EntityKeyValues"] as? AnyObject)!
print("sub_subfield = \(sub_subfield)")
print("subfields = \(subfield)")
// for key_Subfield in sub_subfield as? [AnyObject] ?? [] {
print("inside loop!")
// converting int and bool values
let ask = (field["Ask"] as? Int)!
let bid = (field["Bid"] as? Int)!
let change = (field["Change"] as? Int)!
let EntityState = (field["EntityState"] as? Int)!
let High = (field["High"] as? Double)!
let ID = (field["ID"] as? Int)!
let IsTemporary = ""//(subfield["IsTemporary"] as? Bool)!
let Low = (field["Low"] as? Double)!
let Value = ""//(key_Subfield["Value"] as? Int)!
// it is crashing here due to multple dictionaries
self.Save_KerbRates(ask: (String(ask)),
bid: (String(bid)),
change: (String(change)),
createDate: (field["CreateDate"] as? String)!,
direction: (field["Direction"] as? String)!,
entityContainerName: "",//(subfield["EntityContainerName"] as? String)!,
entitiySetName:"",// (subfield["EntitySetName"] as? String)!,
entitiyState: (String(EntityState)),
high: (String(High)),
id: (String(ID)),
isTemporary: (String(IsTemporary)),
key:"",// (key_Subfield["Key"] as? String)!,
low: (String(Low)),
symbol: (field["Symbol"] as? String)!,
value: (String(Value)))
// }
}
Update:
After using [[String:Any]]
i'm still getting the wrong value of direction,like this
kerb rates full json = [["Low": 106, "Direction": 0, "EntityState": 2, "EntityKey": {
EntityContainerName = tradebizEntities;
EntityKeyValues = (
{
Key = ID;
Value = 101;
}
);
EntitySetName = "v_openmarketrates";
IsTemporary = 0;
}, "ID": 101, "CreateDate": 04:38:26, "Symbol": PKR, "Change": 0, "Ask": 106, "High": 105.7, "Bid": 105.7], ["Low": 126.9752, "Direction": -1, "EntityState": 2, "EntityKey": {
EntityContainerName = tradebizEntities;
EntityKeyValues = (
{
Key = ID;
Value = 1;
}
);
EntitySetName = "v_openmarketrates";
IsTemporary = 0;
}, "ID": 1, "CreateDate": 07:03:46, "Symbol": EUR, "Change": 0.4403, "Ask": 127.349, "High": 126.7654, "Bid": 126.717],
This parses (and prints) all values in the first level of the dictionary and the value for keys IsTemporary and Value in the second level. All variable names start with a lowercase letter to conform to the naming convention.
The code uses a type alias for convenience.
Be aware that the code does not use any error handling to check the dictionary keys. If it is not guaranteed that all items contain all keys and values you have to use optional bindings.
typealias JSONDictionary = [String:Any]
do {
if let jsonResult = try JSONSerialization.jsonObject(with:data!) as? [JSONDictionary] {
for field in jsonResult {
let ask = field["Ask"] as! Double
let bid = field["Bid"] as! Double
let change = field["Change"] as! Double
let createDate = field["CreateDate"] as! String
let direction = field["Direction"] as! String
let entityState = field["EntityState"] as! Int
let high = field["High"] as! Double
let id = field["ID"] as! Int
let low = field["Low"] as! Double
let symbol = field["Symbol"] as! String
let entityKey = field["EntityKey"] as! JSONDictionary
let isTemporary = entityKey["IsTemporary"] as! Bool
let entityKeyValues = entityKey["EntityKeyValues"] as! [JSONDictionary]
let value = entityKeyValues[0]["Value"] as! Int
print(ask, bid, change, createDate, direction, entityState, high, id, low, symbol, isTemporary, value)
}
}
} catch {
print(error)
}

how to get the particular value from Json?

I am having the Json data as shown below in this I need to get the data that which key value pair for default is 1 then i need to get the remaining dictionaries data and need to be passed to the user to display can any one tell me how to implement this ?
And my code is as shown below
if let addressArray = jsonObj!.value(forKey: "address") as? NSArray{
for array in addressArray {
if let addressDict = array as? NSDictionary{
if let Default = addressDict.value(forKey: "default"){
}
}
}
}
"address": [
{
"default": 0,
"number": 9123456711,
"name": "Ramesh",
"address": "No:11/111 ,cross street,Nungambakkam,mylapore,chennai :600088"
},
{
"default": 1,
"number": 8123456722,
"name": "Vignesh",
"address": "No:22/222 ,cross street,Perambur,chennai :600012"
},
{
"default": 0,
"number": 7123456733,
"name": "Rajesh",
"address": "No:33/333 ,cross street,Villivakkam,chennai :600045"
}
]
You can check if Default equals 1 and add those values to an array.
var defaultArray = [NSDictionary]()
if let addressArray = jsonObj!.value(forKey: "address") as? NSArray{
for array in addressArray {
if let addressDict = array as? NSDictionary{
if let Default = addressDict.value(forKey: "default"){
if Default == 1 {
defaultArray.append(addressDict)
}
}
}
}
}
Step1: Prepare your model as shown in below code snippet.
class Addresses: NSObject {
var default = 0
var number = 0
var name = String()
var address = String()
init?(dictionary:[String:Any]) {
guard let default = dictionary["default"],
let number = dictionary["number"],
let name = dictionary["name"],
let address = dictionary["address"]
else {
return nil
}
self.default = default
self.number = number
self.name = name
self.address = address
}
}
Step2: Declare an array to store parsed addresses.
var addressesArray = [Addresses]()
Step3:
if let addressArray = jsonObj!.value(forKey: "address") as? NSArray{
for array in addressArray {
if let addressDict = array as? NSDictionary{
if let defaultValue = addressDict.value(forKey: "default") as? Int{
if defaultValue == 1 {
if let address = Addresses(dictionary: addressDict) {
addressesArray.append(address)
}
}
}
}
}
}
Thats it, take care of datatypes, and you can use addressesArray to display data.

Why can I not access the second level of this array in Swift?

I have the following array which is passed from an API call from a PHP Script:
["playerForm": {
1 = (
{
date = "2017-01-31";
name = Dicky;
result = L;
"results_id" = 42;
},
{
date = "2016-12-24";
name = Dicky;
result = W;
"results_id" = 19;
}
);
2 = (
{
date = "2017-01-25";
name = G;
result = W;
"results_id" = 38;
},
{
date = "2017-01-25";
name = G;
result = D;
"results_id" = 40;
},
{
date = "2017-01-21";
name = G;
result = L;
"results_id" = 34;
}
);
3 = (
{
date = "2017-01-31";
name = Sultan;
result = W;
"results_id" = 42;
},
{
date = "2017-01-15";
name = Sultan;
result = L;
"results_id" = 30;
}
);
}]
However I cannot seem to access the 1,2,3 parts of it...
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print (json!)
if let dict = json?["playerForm"] as? [String:AnyObject] {
print ("step 1")
if let arr = dict["1"] as? [[String:String]] {
print ("step 2")
self.leagueForm = arr.flatMap { Form($0) }
print (self.leagueForm)
print (self.leagueForm.count)
for i in 0..<self.leagueForm.count {
let form = self.leagueForm[i]
print (form.player_results!)
self.formGuide.append(form.player_results!)
}
print ("now")
print (self.formGuide)
self.resultsDisplay.results = self.formGuide
self.resultsDisplay.results = self.resultsDisplay.results.reversed()
self.resultsDisplay.displayResults()
}
}
With this code above it only gets as far as Step 1.
What am I doing wrong?
UPDATED WITH PROGRSS*
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
print (json!)
if let dict = json?["playerForm"] as? [String:AnyObject] {
print ("step 1")
for (_ , value) in dict {
if let arr = value as? [[String:Any]] {
print(arr)
//your code
}
}
}
Custom Struct to define array:
struct Form {
var player_result: String?
var player_name: String?
var result_date: String?
var result_id: String?
init(_ dictionary: [String : Any]) {
self.player_result = dictionary["result"] as? String ?? ""
self.player_name = dictionary["name"] as? String ?? ""
result_date = dictionary["date"] as? String ?? ""
result_id = String(dictionary["results_id"] as? Int ?? 0)
}
}
Change your array type [[String:String]] to [[String:Any]] because it contains both String and Number as value.
if let arr = dict["1"] as? [[String:Any]] {
print(arr)
//your code
}
Note: You need to loop through the dict Dictionary because its each key having array.
for (_ , value) in dict {
if let arr = value as? [[String:Any]] {
print(arr)
//your code
}
}

NSMutableArray true convert to json output and post it to remote with Alamofire in Swift 3

I have NSMutableArray codes from CoreData and I want convert it to Json Array and post it to remote With Alamofire, I try to convert myArray to jsonArray but dont do true. My codes under below.
let maras = try appDelegate.managedObjectContext.fetch(fetchRequest) as! [Manager]
if maras.count > 1 {
let prod: NSMutableDictionary = NSMutableDictionary()
let prodArray:NSMutableArray = NSMutableArray()
for i in 0 ..< maras {
let a = maras[i]
prod.setValue(a.val1, forKey: "val1")
prod.setValue(a.val2, forKey: "val2")
prod.setValue(a.val3, forKey: "val3")
prod.setValue(a.val4, forKey: "val4")
prodArray.add(prod)
}
print(prodArray) // OUTOUT UNDER BELOW
Under below Output prodArray wrong json
(
{
val1 = "2324";
val2 = "1212";
val3 = 234;
val4 = "234234";
},
{
val1 = "223324";
val2 = "12232312";
val3 = 233242344;
val4 = "234223423434";
}
)
must be valid JSON like under below. ( Also I have SwiftyJson in my project)
[{
"val1": "2324",
"val2": "1212",
"val3": 234,
"val4": "234234"
}, {
"val1": "223324",
"val2": "12232312",
"val3": 233242344,
"val4": "234223423434"
}]
After that I want to post my prodArray to remote with Alamofire.My codes under below
Alamofire.request(Posturl, method: .post, parameters: prodArray, encoding: URLEncoding.httpBody, headers: headers)
.responseData{ response in
let success = json["status"]["type"].boolValue
if success == true {
}
}
var json:[String:Any] = [:]
var jsonItem:[String:Any] = [:]
var jsonItemArray:[[String:Any]] = []
jsonItem = [:]
jsonItem["val1"] = "2324"
jsonItem["val2"] = "1212"
jsonItem["val3"] = 234
jsonItem["val4"] = "234234"
jsonItemArray.append(jsonItem)
jsonItem = [:]
jsonItem["val1"] = "223324"
jsonItem["val2"] = "12232312"
jsonItem["val3"] = 233242344
jsonItem["val4"] = "234223423434"
jsonItemArray.append(jsonItem)
print(jsonItemArray)
json["data"] = jsonItemArray
print(json)
[["val2": "1212", "val3": 234, "val4": "234234", "val1": "2324"], ["val2": "12232312", "val3": 233242344, "val4": "234223423434", "val1": "223324"]]
["data": [["val2": "1212", "val3": 234, "val4": "234234", "val1": "2324"], ["val2": "12232312", "val3": 233242344, "val4": "234223423434", "val1": "223324"]]]
you should change your code to:
var prodArray:[[String:Any]] = []
for i in 0 ..< maras {
let a = maras[i]
let prod:[String:Any]
prod["val1"] = a.val1
prod["val2"] = a.val2
prod["val3"] = a.val3
prod["val4"] = a.val4
prodArray.append(prod)
}

create dictionary from objects and keys arrays in swift 2

I have Keys array and Objects array and I want to create a dictionary that each key at index Y in keys array refers to the object at the same index Y in objects array i.e. I want to make code like this but in Swift 2:
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObjects:ObjectsArray forKeys:KeysArray];
let keys = [1,2,3,4]
let values = [10, 20, 30, 40]
assert(keys.count == values.count)
var dict:[Int:Int] = [:]
keys.enumerate().forEach { (i) -> () in
dict[i.element] = values[i.index]
}
print(dict) // [2: 20, 3: 30, 1: 10, 4: 40]
or more functional and generic approach
func foo<T:Hashable,U>(keys: Array<T>, values: Array<U>)->[T:U]? {
guard keys.count == values.count else { return nil }
var dict:[T:U] = [:]
keys.enumerate().forEach { (i) -> () in
dict[i.element] = values[i.index]
}
return dict
}
let d = foo(["a","b"],values:[1,2]) // ["b": 2, "a": 1]
let dn = foo(["a","b"],values:[1,2,3]) // nil
This is a generic solution
func dictionaryFromKeys<K : Hashable, V>(keys:[K], andValues values:[V]) -> Dictionary<K, V>
{
assert((keys.count == values.count), "number of elements odd")
var result = Dictionary<K, V>()
for i in 0..<keys.count {
result[keys[i]] = values[i]
}
return result
}
let keys = ["alpha", "beta", "gamma", "delta"]
let values = [1, 2, 3, 4]
let dict = dictionaryFromKeys(keys, andValues:values)
print(dict)
Try this:
let dict = NSDictionary(objects: <Object_Array>, forKeys: <Key_Array>)
//Example
let dict = NSDictionary(objects: ["one","two"], forKeys: ["1","2"])
let keyArray = [1,2,3,4]
let objectArray = [10, 20, 30, 40]
let dictionary = NSMutableDictionary(objects: objectArray, forKeys: keyArray)
print(dictionary)
Output:-
{
4 = 40;
3 = 30;
1 = 10;
2 = 20;
}

Resources