英文:
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 "`\(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?
答案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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论