Sebastian Boldt Sebastian Boldt - 3 months ago 12
Swift Question

Create Set of Array in Swift

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 is 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?

hnh hnh
Answer

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 confirm 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