jaytrixz
jaytrixz

Reputation: 4079

Check if Dictionary is inside Array of Dictionaries in Swift 3

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

Answers (4)

Mr. Xcoder
Mr. Xcoder

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

Daniel Hall
Daniel Hall

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

Camo
Camo

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

Daniel Lemire
Daniel Lemire

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

Related Questions