6

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?

3
  • 5
    Object must conform to Hashable, not just Equatable. Commented Aug 30, 2016 at 14:46
  • Possible duplicate of Reduce array to set in Swift Commented Aug 30, 2016 at 14:47
  • It is not a duplicate, I am explicitly asking about the kind of protocol I need to implement. The referenced Thread says nothing about the Hashable Protocol and consists of constructs using reduce which could lead the developer to the wrong solution. This Post is more precise and should not be marked as a duplicate to help other stack overflow users finding a solution for their problem faster. Commented Aug 31, 2016 at 19:56

1 Answer 1

10

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.