I was trying to create a set out of an array to make elements unique.
I thought it would be an elegant approach to use the Set initializer to do this job. So I created an array and tried to initialize my new set using that array.
But the compiler was complaining. I tried it using Integer values and it works like a charm. But with my own class it does not work. I also thought that the Equatable Protocol
is the right way to go .. but as you see, it does not solve my Problem.
Consider the following Playground:
import UIKit
internal struct Object: Equatable {
var a: Int
}
internal func == (lhs:Object,rhs: Object) -> Bool {
return lhs.a == rhs.a
}
let array = [Object(a:1),Object(a:1),Object(a:1),Object(a:1),Object(a:2)]
let set = Set(array) // ERROR
The Compiler is complaining with
can not invoke initializer Set<_> with argument of type [Object]
Which Protocol do I need to implement to makes things work?
If you 'command-click' on Set
in Xcode, it takes you to the definition of the Set
type. And there you go:
/// A collection of unique `Element` instances with no defined ordering.
public struct Set<Element : Hashable> : Hashable, CollectionType ...
As mentioned by Rob, the elements need to conform to Hashable
(which in turn requires Equatable
).
Adjusting your code:
import Foundation
internal struct Object: Hashable {
var a: Int
var hashValue: Int { return a.hash }
}
internal func == (lhs:Object,rhs: Object) -> Bool {
return lhs.a == rhs.a
}
let array = [Object(a:1),Object(a:1),Object(a:1),Object(a:1),Object(a:2)]
let set = Set(array) // SUCCESS