What must you do to have set operations work on cu

2019-06-21 23:29发布

问题:

I made a little playground to do some tests on Set operations with custom objects but they are still failing and I have no idea why.

class User: NSObject {
    let id: String
    init(id: String) {
        self.id = id
        super.init()
    }

    override var hashValue: Int {
        get {
            return id.hashValue
        }
    }

    override var description: String {
        get {
            return id
        }
    }
}


func ==(lhs: User, rhs: User) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

Then, I made two sets of User objects:

let user1 = User(id: "zach")
let user2 = User(id: "john")
let user3 = User(id: "shane")


let user4 = User(id: "john")
let user5 = User(id: "shane")
let user6 = User(id: "anthony")

let userSet1 : Set<User> = [user1, user2, user3]
let userSet2 : Set<User> = [user4, user5, user6]

But when I do an operation like so:

let newSet = userSet1.subtract(userSet2)
print(newSet)

newSet is identical to userSet1 and none of the sets are modified.

What must I do to get these set operations to work?

id:zach -> 4799450060450308971
id:john -> 4799450060152454338
id:shane -> -4799450060637667915
id:john -> 4799450060152454338
id:shane -> -4799450060637667915
id:anthony -> 4799450059843449897
id:shane -> -4799450060637667915
id:anthony -> 4799450059843449897
id:john -> 4799450060152454338

回答1:

You do not get to make up your own idea of what to use as a hash value. The requirement for hashability is: the hash value of two objects must be the same if those two objects are equal.

You have provided a hash value algorithm but you have done nothing about making equatability of your User objects match it.

Here is a User object that is hashable in a set:

func ==(lhs:User, rhs:User) -> Bool {
    return lhs.id == rhs.id
}
class User: Hashable, CustomStringConvertible {
    let id: String
    init(id: String) {
        self.id = id
    }
    var hashValue: Int {
        return id.hashValue
    }
}

Observe that I have removed the complication of making this thing also an NSObject. Things are a bit different if you want to do that; you'll need to think about how NSObject works.



标签: ios swift set