Reputation: 4079
I have an array of dictionaries like this:
var suggestions = [["keyword": "apple", "identifier": "0"], ["keyword": "banana", "identifier": "1"], ["keyword": "carrot", "identifier": "2"]]
I would like to append the suggestions array and before I do that, I want to know if the dictionary already exists inside of my array to prevent duplicates. How can I do that in Swift 3?
I tried to use the contains(where: ([String: String)])
function for Swift 3 but I can't seem to make it work.
UPDATE: The answer by Daniel Hall made it work. Here's the exact code for Swift 3:
let newDictionary = ["keyword": "celery", "identifier": "3"]
if !suggestions.contains(where: {$0 == newDictionary}) {
suggestions.append(newDictionary)
}
Upvotes: 4
Views: 8747
Reputation: 4795
Another good and straightforward solution, a solid alternative to Daniel Hall's answer would be:
let contains = suggestions.map(){$0 == newDictionary}.contains(true)
if !contains{
suggestions.append(newDictionary)
}
I posted this answer, because it doesn't use the contains(where: ([String: String]) throws Bool)
function.
Explanation: Basically, suggestions.map(){$0 == newDictionary}
creates a [Bool]
which contains on each position a Bool
value checking if on that position of the array lies newDicitonary
. Then, .contains(true)
checks if the newDictionary is on any position in the suggestions
array.
Upvotes: 1
Reputation: 13679
I think the solution is more straightforward than the other answers suggest. Just use:
let newDictionary = ["keyword":"celery", "identifier": "3"]
if !suggestions.contains{ $0 == newDictionary } {
suggestions.append(newDictionary)
}
This makes sure that your existing array of dictionaries does not contain the new dictionary you want to add before appending it.
Upvotes: 9
Reputation: 1778
Instead of using dictionaries, you can create a struct representing your data types like.
internal struct Entry {
let id: String
let keyword: String
}
extension Entry: Equatable {
static func == (lhs: Entry, rhs: Entry) -> Bool {
return lhs.id == rhs.id && lhs.keyword == rhs.keyword
}
}
let suggestions: [Entry] = [] //...
let newEntry = Entry(id: "3", keyword: "orange")
if suggestions.contains(newEntry) {
// Do Something
} else {
// Insert maybe?
}
If you prefer to just keep using dictionary, you can use contains
let newEntry = ["keyword": "orange", "identifier": "4"]
let containsEntry = suggestions.contains{ $0["identifier"] == newEntry["identifier"] }
if containsEntry {
// Do something
} else {
// Insert maybe?
}
I would go for the struct option .
Upvotes: 2
Reputation: 3618
Should be as simple as
suggestions.contains(where:{$0.contains(where:{$0=="keyword" && $1=="carrot"})})
where you are checking for a "keyword":"carrot" key-value pair. The syntax is a bit cumbersome because you are looking for something inside something.
Note that the above is shorthand for the full query...
suggestions.contains(where:{
(dict: [String:String])->Bool in dict.contains(where:{
(key: String, value: String) -> Bool in (key=="keyword" && value=="carrot")
})
})
which may or may not appear simpler to you.
Upvotes: 0