swifthashmapset

Set is keeping old object even after the new insertion


All my life I believed, Set will replace the existing Value when inserting new Value to maintain it's unique property. But today I am surprised that it's not,

Code:

enum Action {
    case edit
    case delete
    case update
}

struct Object: Equatable, Hashable {
    let id: String
    let action: Action
    let code: UInt8
    var description: String {
        return "`\(self.action)` on `\(self.id)` with #\(self.code)"
    }
    init(id: String, action: Action, code: UInt8) {
        self.id = id
        self.action = action
        self.code = code
    }
    func hash(into hasher: inout Hasher) {   
        hasher.combine(self.id)
    }
    static func == (lhs: Object, rhs: Object) -> Bool {   
        return lhs.id == rhs.id
    }
}

So I used the property id to maintain unique. When I insert new object with same id and different other values then the Set is kept the old one instead of new insertion.

var collection = Set<Object>()
let obj1 = Object(id: "1", action: .delete, code: 1) // `delete` on `1` with #1
collection.insert(obj1) 
let obj2 = Object(id: "1", action: .update, code: 4) // `update` on `1` with #4
collection.insert(obj2)
print(collection.first!.description) // `delete` on `1` with #1

The print supposed to be for code: 4 as I thought, but it is code: 1. Actually I did used the technique in a search-hungry project and lot of places and it's not worked to be expected today, after long debug I did found this.

Is this the way Set works in Swift or Am I doing something wrong?


Solution

  • The issue there is that you are ignoring the result from the insert method. You should try to insert and if it is not inserted you can update the set.
    Something like:

    if !collection.insert(obj2).inserted {
        collection.update(with: obj2)
    }