Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create Set of Array in Swift

Tags:

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

like image 630
Sebastian Boldt Avatar asked Aug 30 '16 14:08

Sebastian Boldt


1 Answers

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
like image 137
hnh Avatar answered Oct 13 '22 12:10

hnh