Get element from array of dictionaries according to key - swift

I have array like [[:String:Any]]
I have a value string , and i want to extract the element with that key without looping (one line).
To check if its there I used this :
if(array.map{$0["NAME"] as! String}.contains(value)){
Is there a way to also extract this dictionary within this if statement ?

For that no need to map the array. You can use contains(where:)
if array.contains(where: { $0["name"] as? String == value }) {
print("Exist")
}
If you want object(dictionary) from array also than you can use first(where:)
if let dict = array.first(where: { $0["name"] as? String == value }) {
print(dict)
}
For more on first(where:) check this SO Thread

Related

Filter An Array Of Arrays By A Value In Firestore Swift

I'm looking to filter an array of arrays by specific value of one of the keys located within each array. Each nested array is read in from Firestore.
As an object, each nested array would look like this:
struct Video {
var url: String
var submissionDate: Timestamp
var submittingUser: String
}
I'm reading it in like this:
videos = document.get("videos") as? [[String : Any]] ?? nil
So far so good, but when I filter it like this:
filteredVideos = videos.filter { $0[2].contains(self.userIdentification) }
I can't do it without getting the error "Reference to member 'contains' cannot be resolved without a contextual type," an error which I was unable to find any relevant information on SO about.
I have read that some people say "Don't use arrays in Firestore!" but this is a build requirement.
Anyone have any ideas? Basically just need all arrays within the array where userId == submittingUser.
Reference Article:
I tried the answer from here: How to filter out a Array of Array's but no luck for this situation.
It's actually an array of dictionaries, not an array of arrays. All you need to do is construct the right predicate for the filter.
This is basically what your Firestore data looks like:
let videos: [[String: Any]] = [
["url": "http://www...", "submittingUser": "user1"],
["url": "http://www...", "submittingUser": "user2"]
]
This is the user you're looking for:
let userIdentification = "user2"
This is the predicate for the filer:
let filteredVideos = videos.filter { (video) -> Bool in
if let submittingUser = video["submittingUser"] as? String,
submittingUser == userIdentification {
return true
} else {
return false
}
}
You can shorthand this down to a single line if you're okay with force-unwrapping the dictionary (if you're 100% certain every video will have a valid submittingUser value):
let filteredVideos = videos.filter({ $0["submittingUser"] as! String == userIdentification })

Getting Array value in a dictionary swift

I am trying to get key and value in a Dictionary while I am able to the key and map it to a dictionary, I am unable to get the value which is an array.
var dict = [String: [String]]
I was able to get the key as an array which is what I want like:
var keyArray = self.dict.map { $0.key }
How can I get the value which is already an array
Use flatMap if you want to flatten the result you get when you use map which is of type [[String]].
let valueArray = dict.flatMap { $0.value } // gives `[String]` mapping all the values
Here is how you get each string count Array
var dict = [String: [String]]()
let countOfEachString = dict.map { $0.value }.map{ $0.count }
Each value is a string array .. so to access each array you need to use map again

Check if a String is contained in an NSDictionary

I am trying to check if an input from a textfield exists in the NSDictionary but I am not sure how to do this.
let nsdict = snapshot.value as? NSDictionary
let values = nsdict?.allValues
Once I Do this i am not sure on how to cast the values to a string to check with a user input textfield.
For example doing this:
if values.contains(userIinput.text){
print("Found")
}
You can apply a filter. In the following code I create a dictionary, and then I filter looking for the userInput.text. Every value that matches will get stored in the new dictionary matches. If matches is > 0, the input already exists and you will have a dictionary with the keys that have the userInput.text as value. Also, you can check if it matches more than once.
You need to verify that $0.value is an String or that the userInput is not nil because if the user input is nil and the $0.value of the dictionary is not an String it will be will and return a match.
let dict: [String : Any] = ["first" : "String", "Second" : 2]
let matches = dict.filter{
guard let value = $0.value as? String else { return false }
value == userInput.text
}
matches.count
If you just want to check if it already exists you can just
guard let userInput = userInput else { return }
if (!dict.filter{ $0.value as? String == userInput }.isEmpty) {
print ("Found")
}
In the first example I'm verifying that $0.value is an String if not I am returning that it does not match, and in the second I am checking that the userInput is not nil, if not it finishes the function there (you can use and if let if you prefer)

Array from specific keys in a dictionaries array?

I have an array of dictionaries : [[String:String]]
From every dictionary in this array I want only the key "name" to be added into a new array.
I can loop over them obviously, but is there a way with 1 line (similar to array.keys only with specific keys) ?
You can use map for that.
let nameArray = yourArray.map { $0["name"]! }
If all the dictionaries from array not contains name key then use flatMap.
let nameArray = yourArray.flatMap { $0["name"] }

Access data in Dictionary from NSCountedSet objects

I have an NSCountedSet consisting of String objects, if I iterate over the set and print it out, I see something like this:
for item in countedSet {
print(item)
}
Optional(One)
Optional(Two)
The countedSet is created from an Array of String objects:
let countedSet = NSCountedSet(array: countedArray)
If I print the array I see something like this:
["Optional(One)", "Optional(One)", "Optional(One)", "Optional(Two)", "Optional(Two)"]
Now, I want to use those counted strings to access data in a Dictionary, where the keys are String type and the values have the type [String : AnyObject]. If I print the dictionary, I see all the data.
However, if I use of the objects from the countedSet to access the dictionary, I always get a nil value back:
for item in countedSet {
let key = item as? String
let data = dictionary[key!] // Xcode forced me to unwrap key
print(data)
}
nil
nil
But
let key = "One"
let data = dictionary[key]
gives me the expected data.
What am I missing here, how can I access my data from the countedSet objects?
UPDATE: solved thanks to the comment from Martin R. The String objects were originally NSString objects (obtained from NSScanner), and I was casting them wrongly:
let string = String(originalString)
after I changed it to:
let string = (originalString as! String)
All works fine.