Reputation: 11987
Not sure if I need reduce, sorting, filtering or using the newer unique methods. I've even tried Equatable solutions.
I need to auto-identify keys that have matching values and take only those keys and put them into a new dictionary or array.
var userDB: [String:Any] = ["userID1":"gameIDa", "userID2":"gameIDa", "userID3":"gameIDc", "userID4":"gameIDd", "userID5":"gameIDe"]
As you can see only these two IDs have the same value of gameIDa
. I need output of this result.
// [userID1, userID2]
Thanks
Upvotes: 1
Views: 71
Reputation: 32904
Firstly, in order to be able to compare values, the Dictionary
Value
type needs to be an Equatable
one. Once this is fulfilled, you can easily filter the keys that hold the queried value:
extension Dictionary where Value: Equatable {
func keysWithCommonValues() -> [Key] {
// go over all keys and keep ones for which the dictionary has one another key with the same value
return keys.filter { key in contains { $0.key != key && $0.value == self[key] } }
}
}
// userDB is not inferred as [String:String]
var userDB = ["userID1":"gameIDa", "userID2":"gameIDa", "userID3":"gameIDc", "userID4":"gameIDd", "userID5":"gameIDe"]
print(userDB.keysWithCommonValues()) // ["userID1", "userID2"]
Upvotes: 1
Reputation: 11242
You can use Dictionary(grouping:by:) to achieve this easily and then reduce it to a dictionary which contains only entries with multiple values.
var userDB: [String: String] = ["userID1":"gameIDa", "userID2":"gameIDb", "userID3":"gameIDc", "userID4":"gameIDa", "userID5":"gameIDe"]
let dict = Dictionary(grouping: userDB.keys) { userDB[$0] ?? "" }.reduce(into: [String:[String]](), { (result, element) in
if element.value.count > 1 {
result[element.key] = element.value
}
})
dict
["gameIDa": ["userID1", "userID4"]]
Upvotes: 2