Searching in Array of Dictionaries - swift

I'm trying to search values in array of dictionaries which I get from JSON. I have a tableViewController with UISearchResultsUpdating. I found an example with array of Strings:
func updateSearchResultsForSearchController(searchController: UISearchController)
{
filteredTableData.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF contains[c] %#", searchController.searchBar.text)
let array = tableData.filteredArrayUsingPredicate(searchPredicate)
filteredTableData = array as! [String]
self.tableView.reloadData()
}
And I really don't know how to made search in array like this:
(
{
id = 3;
name = TestNewYork;
},
{
id = 2;
name = TestLA;
},
{
id = 1;
name = TestWashington;
}
)
my tableData = [] and filteredTableData must be an array too
Please, help!

You can use a simple filter function to do this...
tableData : [[String : String]] = ... // your JSON array of String, String dictionaries...
filteredTableData = tableData.filter{
dictionary in
return dictionary["name"] == filterString
}
Something like that anyway, not written Swift for a while.
You can wrap it in a function too...
func filter(array : [[String : String]], byString filterString : String) -> [[String : String]] {
return array.filter{
dictionary in
return dictionary["name"] == filterString
}
}
Or something. Not checked the code yet. Will be back if it doesn't work.
Checked in Playground and this works...
UPDATE
Changed to this...
let data = [
[
"id" : 3,
"name" : "a"
],
[
"id" : 4,
"name" : "b"
],
[
"id" : 5,
"name" : "c"
]
]
let filteredData = data.filter{
return $0["name"] == "b"
}
And it works. Just can't work out how to wrap in a function.
If you want to match the beginning of words...
let data = [
[
"id" : 3,
"name" : "Hello"
],
[
"id" : 4,
"name" : "Goodbye"
],
[
"id" : 5,
"name" : "Everybody"
]
]
let filteredData = data.filter{
let string = $0["name"] as! String
return string.hasPrefix("Goo")
}
If you want a contains you just need to do a find in the string.
Again, I'm not lying here. I'm running it in a Playground to check...
For a contains search you can do this...
let filteredData = data.filter{
let string = $0["name"] as! String
return string.rangeOfString("db") != nil
}

Related

how to add dictionary and get values

sorry, I'm trying to add a json of type dictionary and get the values. I don't know if I'm doing it correctly, that's how it works for me, but when I get the values ​​of the function that the dictionary returns, my application doesn't get anything.
I tried to obtain this data in different ways. I don't know if someone could give me any idea, thank you.
let jsonLifevitPBM_200 = """
{
"result" : [
{
"id_d" : 55,
"id_c" : "0",
"data" : [
{
"Diastolic" : 85,
"ErrorCode" : -1,
"Systolic" : 120,
"Pulse" : 72
}
],
"date_s" : "2021-07-28 09:45:16.201"
}
],
"error" : 0,
"flags" : 0
}
"""
let jsonKelvin = Data(jsonLifevitPBM_200.utf8)
let jsonKelvinResult = try? JSONDecoder().decode(VitalSignTermometreResponse.self, from: jsonKelvin)
let temperature = jsonKelvinResult?.result[0].data[0].Temperature
let mode = jsonKelvinResult?.result[0].data[0].Mode
let unit = jsonKelvinResult?.result[0].data[0].Unit
if let tem = temperature , let mod = mode , let uni = unit {
labelsystole.text = "Error: \(tem)"
labeldiastole.text = "Error: \(mod)"
labelPulse.text = "Error: \(uni)"
} else {
labelResult.text = "Error Medisana BU 575 Connect"
}
Another way of trying to create the dictionary and get the data was this way, but I don't think it is in the correct way
let responseDevice : [String : Any] = [
"result" : [
"id_d" : 55,
"id_c" : "0",
"data" : [
"Diastolic" : 85,
"ErrorCode" : -1,
"Systolic" : 120,
"Pulse" : 72
],
"date_s" : "2021-07-28 09:45:16.201"
]
]
if let dat = responseDevice["result"] as? [String : Any] {
if let resultData = dat["data"] as? [String : Any] {
if let diast = resultData["Diastolic"] as? String ,
let systolic = resultData["Systolic"] as? String {
println("Result : \(diast) - \(systolic)")
}
}
}
I think the best way to do that is to use a third party library to get JSON and after that you can manage JSON values.
https://github.com/SwiftyJSON/SwiftyJSON

Beginner Swift: Converting string if letter in dictionary

Thanks for your help - just starting out so imagine there's some serious issues with my logic here.
Trying to write a program, given an input, if a letter from that input is found in a dictionary, replace the letter with the corresponding value.
Really stuck where I'm going wrong. Anyone able to help / suggest an alternative logic that may work?
var leetDic = ["A" : "4",
"B" : "6",
"E" : "3",
"I" : "1",
"L" : "1",
"M" : "(V)",
"N" : "(/)",
"O" : "0",
"S" : "5",
"T" : "7",
"V" : "(/",
"W" : "`//]"]
func leetConverter(leet: String) {
var leet1 = leet.uppercased()
for i in leet1.characters {
if i == leetDic.keys { //ERROR "Binary operator cannot be applied to operands of type Character and dictionary"
i = leetDic.values // ERROR "cannot assign value 'i' is a let constant"
} else {
return i
}
}
}
var test = leetConverter(leet: "Hello World")
Problem is you are comparing character and array also you can assign value to i in loop because it is constant you can go like this way.
func leetConverter(leet: String) -> String {
var leet1 = leet.uppercased()
var newString = String()
for ch in leet1.characters {
let str = String(ch)
if let value = leetDic[str] {
newString.append(value)
} else {
newString.append(str)
}
}
return newString
}
More Swifty way
func leetConverter(leet: String) -> String {
let str = leet.characters.map { leetDic[String($0).uppercased()] ?? String($0) }.joined()
return str
}

How to sort array of NSMutableDictionary store in NSUserDefault?

I have an array of NSMutableDictionary saved with NSUserDefault , I want to sort the array based on "timestamp" key (the value is a String) in each NSMutableDictionary :
that the code I use to retrieve the array:
if let chatsArray = NSUserDefaults().arrayForKey("myChatsList") as? [NSMutableDictionary]{
print(chatsArray)
//sort the array
print(sortedArray)
}
thats how my array look like:
[{
eventBadge = 1;
eventId = "-KWE39B6Dh7rDzaF-xy4";
lastMessage = uyfgduihgvifudhviufhvdf;
timestamp = 20;
unreadMessage = 2;
}, {
eventBadge = 1;
eventId = "-KWWc99ex8f7ksq8TR2U";
lastMessage = uyfgduihgvifudhviufhvdf;
timestamp = 5;
unreadMessage = 1;
}, {
eventBadge = 1;
eventId = "-KWE5OYRZnZ5-p3LUotL";
lastMessage = uyfgduihgvifudhviufhvdf;
timestamp = 10;
unreadMessage = 2;
}]
I try to use NSSDescriptor :
var descriptor: NSSortDescriptor = NSSortDescriptor(key: "timestamp", ascending: true)
chatsArray.sortedArrayUsingDescriptors([descriptor])
and also to use a typed array (after using a new class)
mutableChatsArray.sortInPlace{ ($0.compare($1.timestamp) == NSComparisonResult.OrderedDescending)}
So far without success...
Thanks for your help
Swift 3 example
let chatsArray = [[
"eventBadge" : 1,
"eventId" : "-KWE39B6Dh7rDzaF-xy4",
"lastMessage" : "uyfgduihgvifudhviufhvdf",
"timestamp" : 20,
"unreadMessage" : 2,
], [
"eventBadge" : 1,
"eventId" : "-KWWc99ex8f7ksq8TR2U",
"lastMessage" : "uyfgduihgvifudhviufhvdf",
"timestamp" : 5,
"unreadMessage" : 1,
], [
"eventBadge" : 1,
"eventId" : "-KWE5OYRZnZ5-p3LUotL",
"lastMessage" : "uyfgduihgvifudhviufhvdf",
"timestamp" : 10,
"unreadMessage" : 2,
]] as [[String:Any]]
// to get the timestamp value and store it inside an array with order
let arrayTimeStamp = (chatsArray.flatMap{$0["timestamp"]} as! Array<Int>).sorted(by: >)
print(arrayTimeStamp) // [20, 10, 5]
//to order an array of dictionaries
let TimeStamp = chatsArray.sorted{$0["timestamp"] as! Int > $1["timestamp"] as! Int }
print(TimeStamp)
//[["eventId": "-KWE39B6Dh7rDzaF-xy4", "lastMessage":"uyfgduihgvifudhviufhvdf", "timestamp": 20, "unreadMessage": 2, "eventBadge": 1],
//["eventId": "-KWE5OYRZnZ5-p3LUotL", "lastMessage": "uyfgduihgvifudhviufhvdf", "timestamp": 10, "unreadMessage": 2, "eventBadge": 1],
//["eventId": "-KWWc99ex8f7ksq8TR2U", "lastMessage": "uyfgduihgvifudhviufhvdf", "timestamp": 5, "unreadMessage": 1, "eventBadge": 1]]
Working with NSUserDefaults can be very annoying. I usually follow this technique when getting and setting data from the defaults.
var mutableArray = defaults.objectForKey("Your Array") as? NSMutableArray
mutableArray.sortInPlace { (a, b) -> Bool in
a.start!.compare(b.start!) == NSComparisonResult.OrderedAscending
}
defaults.setValue(mutableArray forKey: "Your Array")
#Rob and #Fallah , thanks for your answers , Im gonna check them, for now I solve my issue by using the NNSSDescriptor and add it a selector:
let descriptor: NSSortDescriptor = NSSortDescriptor(key: "timestamp", ascending: true, selector: #selector(NSString.localizedStandardCompare(_:)))
let sortedChatsArray = (chatsArray as NSArray).sortedArrayUsingDescriptors([descriptor])

Are there different solution how retrieve waypoints?

"-KHbCuQflKHrJiUmfpG0" : {
"waypoints" : {
"-KHbCuQflKHrJiUmfpG1" : {
"latitude" : 13.17078652595298,
"longitude" : -59.5775944578738
},
"-KHbCuQflKHrJiUmfpG2" : {
"latitude" : 13.15541190861343,
"longitude" : -59.57619643155932
},
"-KHbCuQg9W_tebl1pU66" : {
"latitude" : 13.148444967591,
"longitude" : -59.5589266947333
}
},
"subtitle" : "jamesrick",
"title" : "Highway",
"type" : "polyline"
},
I have this structure for lines in Firebase. How retrieve all data with also nested node waypoints?
ref.observeEventType(.Value, withBlock: { polylines in
if let objects = polylines.children.allObjects as? [FDataSnapshot] {
for object in objects {
polylineDictionary = object.values as? Dictionary<String, AnyObjects> {
// ? ? ?
}
}
}
})
Now I have access to title, subtitle, type but how obtain access to waypoints? When I use
`polylineDictionary["waypoints"] as? [String: [String:Double]]`
so this dictionaries are not ordered. Thanks for some advice.
This is how I would get the nested waypoints... it's basically by iterating through the keys... I would also add some error checking when grabbing the longitude and latitudes to make sure they're there, but this is the gist:
if let polylineDictionary["waypoints"] as? [String: [String:Double]] {
let waypoints = Array(polylineDictionary.keys)
for i in 0..<waypoints.count {
let waypointId = waypoints[i]
let latitude = polylineDictionary[waypointId]["latitude"]
let longitutde = polylineDictionary[waypointId]["longitude"]
}
}
It's not clear from the question about ordering; if you just want to get to the waypoints, it's pretty straight forward:
Assume your complete Firebase structure is:
root_node
"-KHbCuQflKHrJiUmfpG0" : {
"waypoints" : {
"-KHbCuQflKHrJiUmfpG1" : {
"latitude" : 13.17078652595298,
"longitude" : -59.5775944578738
},
"-KHbCuQflKHrJiUmfpG2" : {
"latitude" : 13.15541190861343,
"longitude" : -59.57619643155932
},
"-KHbCuQg9W_tebl1pU66" : {
"latitude" : 13.148444967591,
"longitude" : -59.5589266947333
}
},
"subtitle" : "jamesrick",
"title" : "Highway",
"type" : "polyline"
}
Suppose I want the data for this specific node, -KHbCuQflKHrJiUmfpG0
let nodeRef = rootRef.childByAppendingPath("-KHbCuQflKHrJiUmfpG0")
nodeRef.observeSingleEventOfType(.Value , withBlock: { snapshot in
print(snapshot.value) //prints everything in the node
let title = snapshot.value["title"] as! String //to get any element
print(title) //prints Highway
var waypoints = [String: [String:String]]() //dict to hold key:value, unordered
waypoints = snapshot.value["waypoints"] as! Dictionary
print(waypoints) //prints the 3 waypoints and their children (as a dict)
//get fancy and convert the dictionary to an array (which can be sorted)
let arr = waypoints.map {"\($0) \($1)"}
for point in arr {
print(point)
}
}

Json results to a string array in swift

Hello i've been trying to make a json request and some of its results i want to put it to an array of string.
So i have the following code
var arrRes = [[String:AnyObject]]()
var nameaRR = [String]()
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request(.GET, "https://graph.facebook.com/search", parameters: ["q": "", "type": "place", "center": "37.928319,23.7036673", "distance": "10000","limit": "1000", "access_token": "SomeToken", "expires_in": "5184000"])
.responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
let swiftyJsonVar = JSON(responseData.result.value!)
//print(swiftyJsonVar)
if let resData = swiftyJsonVar["data"].arrayObject {
self.arrRes = resData as! [[String:AnyObject]]
self.nameaRR = swiftyJsonVar["data"]["name"] as! [String]
print(self.nameaRR)
}
if self.arrRes.count > 0 {
self.kati.reloadData()
}
}
}
}
The JSON Resul is the following
{
"data" : [
{
"category_list" : [
{
"id" : "272705352802676",
"name" : "Outdoors"
},
{
"id" : "115725465228008",
"name" : "Region"
}
],
"id" : "552889064768971",
"name" : "Παλαιο Φαληρο", //This String i want to put in an Array
"category" : "Local business",
"location" : {
"street" : "",
"city" : "Palaión Fáliron",
"country" : "Greece",
"longitude" : 23.6944070162,
"zip" : "17562",
"latitude" : 37.9284637008,
"state" : ""
}
}
]
}
I get a warning
Cast from 'JSON' to unrelated type '[String]' always fails
But i'm stuck of how can i put all the Strngs to the array nameaRR.
Can anyone help me find my mistake? Thanks!
look do like that
if let resData = swiftyJsonVar["data"] as? [[String:AnyObject]] {
if let categorylist = resData["category_list"] as? [[String:AnyObject]]{
if let id = categorylist["id"] as? Int{
print(id)
}
}
}