Set在新插入后仍然保留了旧对象。

huangapple go评论140阅读模式
英文:

Set is keeping old object even after the new insertion

问题

以下是翻译好的部分:

我一直以为,当插入新值以维护其唯一性属性时,`Set`会替换现有的值。但今天我感到惊讶,原来不是这样的。

**代码:**

    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)`上的`\(self.id)`,带有 #\(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
        }
    }

所以我使用属性`id`来维护唯一性。当我插入具有相同`id`但其他不同值的新对象时,`Set`会保留旧对象,而不是插入新对象。

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

***

我原以为打印的应该是`code: 4`,但实际上是`code: 1`。事实上,在一个需要高效搜索的项目中,我使用了这种技术,并在很多地方都使用了,但今天经过长时间的调试,我发现了这个问题。

Swift中是这样的工作方式吗?还是我做错了什么?
英文:

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 &quot;`\(self.action)` on `\(self.id)` with #\(self.code)&quot;
    }
    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) -&gt; 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&lt;Object&gt;()
let obj1 = Object(id: &quot;1&quot;, action: .delete, code: 1) // `delete` on `1` with #1
collection.insert(obj1) 
let obj2 = Object(id: &quot;1&quot;, 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?

答案1

得分: 2

如果你忽略了插入方法的结果,那里的问题就出在这里。你应该尝试插入,如果没有插入成功,你可以更新集合。类似这样:

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

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)
}

huangapple
  • 本文由 发表于 2023年8月11日 05:13:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76879338.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定