Swift: How to filter json data - arrays

if a NSArray data like this:
var arrayData:NSArray = [{name:"aaa",tel:"0000"},{name:"bbb",tel:"0000"}]
how do I filter name = "aaa"
thanks.

In Swift you can use the filter method in Array. The method takes a closure indicating whether to include the value in the new array. For example:
let array: NSArray = ["aaa", "bbb", "ccc"]
let fiteredArray = (array as! Array).filter { $0 != "aaa" }
filteredArray now only contains "bbb" and "ccc".

Related

Cannot assign value of type '[String]' to type '[[String : Any]]'

Swift Xcode version 13.2.1
Here we have two Arrays,(1)var dicSearch=String and (2)var searchingDic: [[String: Any]]=[] I want to assign searchingDic to dicSearch when i implement it than it show error like, Cannot assign value of type '[String]' to type '[[String : Any]]'
here's my code, please anyone help!
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchingDic = dicSearch.filter{filtering in
let filterService = filtering["fName"] as? String
return((filterService?.lowercased().contains(searchText.lowercased()))!)
}
It looks like you are trying to create a filtered list based on a search term, but your dicSearch type is an array of strings (i.e: [String]), while your searchingDic is an array of dictionaries (i.e: [[String : Any]]).
This might be confusing when coming from a different language, but in Swift, the following declaration is a dictionary:
var dict: [String: Any] = [
"key1": "value1",
"key2": "value2",
]
so the following:
var arrayOfdicts: [[String: Any]] = [
["foo": "bar"],
["apples": "oranges"],
dict
]
is actually an array, containing a list of dictionaries, notice how I've put the dict declared above in the second array.
The compiler is telling you that you cannot assign a '[String]' to type '[[String : Any]]'
because this:
// example to an array of strings
var fullList: [String] = [
"apples",
"bananas",
"cucumbers"
]
// is not the same as
var arrayOfdicts: [[String: Any]] = [
["foo": "bar"],
["apples": "oranges"],
dict
]
The Array#filter method, iterates the array itself, and returns a new array with only the elements that return true in the return statement.
so either both your arrays need to be [String] or both your arrays need to be [[String:Any]]
example for String arrays:
// array
var fullList: [String] = [
"apples",
"bananas",
"cucumbers"
]
var filteredList: [String] = []
var searchTerm = "b"
filteredList = fullList.filter{ item in
let value = item
return value.lowercased().contains(searchTerm)
}
print(filteredList) // prints ["bananas", "cucumbers"]
an example for filtering with array of dictionaries:
var people: [[String: Any]] = [
["name": "Joe"],
["name": "Sam"],
["name": "Natalie"],
["name": "Eve"]
]
var filteredPeople: [[String: Any]] = []
var nameFilter = "a"
filteredPeople = people.filter{ item in
let value = item["name"] as! String
return value.lowercased().contains(nameFilter)
}
print(filteredPeople) // prints [["name": "Sam"], ["name": "Natalie"]]
Hope this helps :)

Extracting elements from a array of dictionaries

I have a array of dictionaries. From here I want to extract individual elements
The following code is generating an array which has multiple dictionaries. From this I need to extract values which match a certain key.
Code used:
return array.filter{namePredicate.evaluate(with: $0)}
This looks like:
[["a":"1","b":"2","c":3],["a":"3","b":"4","c":5]]
From this I need to extract values for key "a" ie 1, 3. How do I go about this?
Use compactMap:
let aValues = filteredArray.compactMap { $0["a"] }
where filteredArray is the array returned from array.filter{namePredicate.evaluate(with: $0)}.
please informed that, the filter will return the same type as the array it self, the map will return the new type you mean to return. so if you want to get the different type with it self, you need to use map function.
and in map functions "map" will return the same number of elements as the array it self, the "compactMap" will remove the 'nil' value.
so if you make sure all the 'dict' in your array have the key you need to get, you can use map, or you can you use compactMap to avoid nil value in the result array
so you can use
let arr = [["a":"1","b":"2","c":3],["a":"3","b":"4","c":5]]
let test = arr.map{$0["a"] as? String}
let test2 = arr.compactMap{$0["a"] as? String}
If you need to do with for multiple keys, you can make a merged dictionary that maps all keys to arrays of all values. You lose the ordering of the values, so this will only work if it's not necessary.
func merge<Key, Value>(dicts: [[Key: Value]]) -> [Key: [Value]] {
return dicts.reduce(into: [:]) { accumalatorDict, dict in
accumalatorDict.merge(
dict.mapValues({ [$0] }),
uniquingKeysWith: { return $0 + $1 }
)
}
}
let dicts: [[String: Any]] = [
["a":"1","b":"2","c":3],
["a":"3","b":"4","c":5]
]
let mergedDicts = merge(dicts: dicts)
for (key, values) in mergedDicts {
print(key, values)
}
let allValuesForA = mergedDicts["a"]
print(allValuesForA) // => ["1", "3"]
try this
let arr = [["a":"1","b":"2","c":3],["a":"3","b":"4","c":5]]
let test = arr.map{$0["a"] as? String}

How to convert Strings in Swift?

I've two cases where I need to convert strings to different formats.
for ex:
case 1:
string inputs: abc, xyz, mno, & llr // All Strings from a dictionary
output: ["abc","xyz", "mno", "llr"] //I need to get the String array like this.
But when I use this code:
var stringBuilder:[String] = [];
for i in 0..<4 {
stringBuilder.append("abc"); //Appends all four Strings from a Dictionary
}
print(stringBuilder); //Output is 0: abc, 1:xyz like that, how to get desired format of that array like ["abc", "xyz"];
Real usage:
let arr = Array(stringReturn.values);
//print(arr) // Great, it prints ["abc","xyz"];
let context = JSContext()
context?.evaluateScript(stringBuilder)
let testFunction = context?.objectForKeyedSubscript("KK")
let result = testFunction?.call(withArguments:arr); // Here when I debugger enabled array is passed to call() like 0:"abc" 1:"xyz". where as it should be passed as above print.
Secondly how to replace escape chars in swift: I used "\" in replaceOccurances(of:"\\'" with:"'"); but its unchanged. why and how to escape that sequnce.
case 2:
string input: \'abc\'
output: 'abc'
To get all values of your dictionary as an array you can use the values property of the dictionary:
let dictionary: Dictionary<String, Any> = [
"key_a": "value_a",
"key_b": "value_b",
"key_c": "value_c",
"key_d": "value_d",
"key_e": 3
]
let values = Array(dictionary.values)
// values: ["value_a", "value_b", "value_c", "value_d", 3]
With filter you can ignore all values of your dictionary that are not of type String:
let stringValues = values.filter({ $0 is String }) as! [String]
// stringValues: ["value_a", "value_b", "value_c", "value_d"]
With map you can transform the values of stringValues and apply your replacingOccurrences function:
let adjustedValues = stringValues.map({ $0.replacingOccurrences(of: "value_", with: "") })
// adjustedValues: ["a", "b", "c", "d"]
Why not try something like this? For part 1 of the question that is:
var stringReturn: Dictionary = Dictionary<String,Any>()
stringReturn = ["0": "abc","1": "def","2": "ghi"]
print(stringReturn)
var stringBuilder = [String]()
for i in stringReturn {
stringBuilder.append(String(describing: i.value))
}
print(stringBuilder)
Also, part 2 seems to be trivial unless I'm not mistaken
var escaped: String = "\'abc\'"
print(escaped)
case 1:
I have Implemented this solutions, Hope this will solve your problem
let dict: [String: String] = ["0": "Abc", "1": "CDF", "2": "GHJ"]
var array: [String] = []
for (k, v) in dict.enumerated() {
print(k)
print(v.value)
array.append(v.value)
}
print(array)
case 2:
var str = "\'abc\'"
print(str.replacingOccurrences(of: "\'", with: ""))

Get only the string value from NSArray output

I am storing values from Json response like
self.NameArray = self.attachmentsArray.valueForKey("filename") as! NSArray
Output:
NameArray(("Din.pdf","img.jpeg"),(),(),("41_58"))
I got this output. I need to get the array only having ("Din.pdf","img.jpeg","41_58").
How to get it using swift code?
Convert NSArray to Swift Type [[String]]:
let NameArray:NSArray = [["Din.pdf","img.jpeg"], [], [], [ "41_58" ]]
let swiftArray = NameArray as! [[String]]
let flattenedArray = swiftArray.flatMap{ $0 }
Credits: Eric Aya and Flatten a Array of Arrays in Swift
If you do not want to convert it into Swift Type:
let NameArray:NSArray = [["Din.pdf","img.jpeg"], [], [], [ "41_58" ]]
let arrFiltered:NSMutableArray! = []
for arr in NameArray {
for a in arr as! NSArray {
arrFiltered.addObject(a)
}
}
print(arrFiltered)

How to append an array in another array in Swift?

I have a JSON response whose answer I have to parse. I write the single elements into an array called courseDataArray using a for loop. After that, I want to write this newly created array into another array called combinedCourseArray with the aim to pass that on to a UITableView. Creating the first array seems to work fine.
But how can I create another array combinedCourseArray who contain all arrays of type courseDataArray?
for (index, element) in result.enumerate() {
// get one entry from the result array
if let courseEntry = result[index] as? [String:AnyObject]{
//work with the content of the array
let courseName = courseEntry["name"]
let courseType = courseEntry["course_type"]
let courseDate = courseEntry["cor_date"]
let courseId = courseEntry["cor_id"]
let duration = courseEntry["duration"]
let schoolId = courseEntry["sco_id"]
let status = courseEntry["status"]
let courseDataArray = ["courseName" : courseName, "courseType": courseType, "courseDate": courseDate, "courseId": courseId, "duration": duration, "schoolId":schoolId, "status":status]
print(courseDataArray)
var combinedCourseArray: [String: AnyObject] = [:]
combinedCourseArray[0] = courseDataArray //does not work -- error: cannot subscript a value of type...
// self.shareData.courseStore.append(scooter)
}
You should move the combinedCourseArray declaration outside of the array. It should be var combinedCourseArray: [[String: AnyObject]] = [[:]] since it's an array and not a dictionary.
And you should be doing
combinedCourseArray.append(courseDataArray)
instead of
combinedCourseArray[0] = courseDataArray
var FirstArray = [String]()
var SecondArray = [String:AnyObject]()
FirstArray.append(contentsOf: SecondArray.value(forKey: "key") as! [String])
First declare this combinedCourseArray array out side this loop
var combinedCourseArray: [[String: AnyObject]] = [[String: AnyObject]]()
for (index, element) in result.enumerate() {
// get one entry from the result array
if let courseEntry = result[index] as? [String:AnyObject]{
//work with the content of the array
let courseName = courseEntry["name"]
let courseType = courseEntry["course_type"]
let courseDate = courseEntry["cor_date"]
let courseId = courseEntry["cor_id"]
let duration = courseEntry["duration"]
let schoolId = courseEntry["sco_id"]
let status = courseEntry["status"]
let courseDataArray = ["courseName" : courseName, "courseType": courseType, "courseDate": courseDate, "courseId": courseId, "duration": duration, "schoolId":schoolId, "status":status]
print(courseDataArray)
combinedCourseArray.append(courseDataArray) //does not work -- error: cannot subscript a value of type...
// self.shareData.courseStore.append(scooter)
}
}
Just use flatMap on the outer array to translate one array into another array, possibly dropping some elements:
let courseDataArray : [[String:AnyObject?]] = result.flatMap {
guard let courseEntry = $0 as? [String:AnyObject] else {
return nil
}
return [
"courseName" : courseEntry["name"],
"courseType": courseEntry["course_type"],
"courseDate": courseEntry["cor_date"],
"courseId": courseEntry["cor_id"],
"duration": courseEntry["duration"],
"schoolId": courseEntry["sco_id"],
"status": courseEntry["status"]
]
}
Of course, the guard isn't really necessary since the input type is presumably already [[String:AnyObject]] and since you then can't have any internal failures, you can just use map instead of flatMap

Resources