一组对象中的 属性 怎么可能符合 Swift 中的 Hashable 协议?
How is possible to a property in a Set of objects conform to Hashable protocol in Swift?
我正在为项目列表实现标签功能。我正在尝试实现一个计算的 属性 计算项目列表中的标签集作为每个项目的不同标签集的联合,例如:
item1 - [tag1, tag2]
item2 - [tag1, tag3]
输出 > [tag1, tag2, tag3]
问题是标签 class 需要是可散列的,并且在标签的每个实例中都给出一个 UID,即使是具有相同描述的标签。因此,当我循环所有项目标签列表以创建整个列表的标签集时,结果是错误的,如:
输出 > [tag1, tag1, tag2, tag3]
代码如下:
class TTDItem: Identifiable {
var id: UUID = UUID()
var itemDesc: String
var itemTags: Set<TTDTag>
init(itemDesc: String, itemTags: Set<TTDTag>) {
self.itemDesc = itemDesc
self.itemTags = itemTags
}
}
class TTDTag: Identifiable, Hashable {
var TTDTagDesc: String
var hashValue: Int {
return id.hashValue
}
init(TTDTagDesc: String){
self.TTDTagDesc = TTDTagDesc
}
static func ==(lhs: TTDTag, rhs: TTDTag) -> Bool {
return lhs.id == rhs.id
}
}
class TTDItemList {
var itemList: [TTDItem]
init(itemList: [TTDItem]) {
self.itemList = itemList
}
//(...)
// implement computed property taglist
func itemTagsList()-> Set<TTDTag> {
var tagSet = Set<TTDTag>()
for item in self.itemList {
tagSet = tagSet.union(item.itemTags)
}
return tagSet
}
}
如何才能只访问标签描述以获得正确的结果?谢谢
这可以使用 reduce
和 union
函数来完成
func itemTagsList()-> Set<TTDTag> {
itemList.map(\.itemTags).reduce(Set<TTDTag>()){ [=10=].union() }
}
请注意,对于 Hashable
,您需要为 TTDTag
实施 hash(into:)
func hash(into hasher: inout Hasher) {
hasher.combine(TTDTagDesc)
}
您应该 属性 名称以小写字母开头并使它们具有描述性,这样也许您可以将 TTDTagDesc
更改为 tagDescription
hashValue
已弃用(您应该已经收到警告)。您应该覆盖 hash(into:)
并在那里使用您的 TTDTagDesc
属性。
此外,您应该将 id
实现为 return TTDTagDesc
,因为这是 识别 标签的方式。
class TTDTag: Identifiable, Hashable {
var TTDTagDesc: String
// Note here
func hash(into hasher: inout Hasher) {
hasher.combine(TTDTagDesc)
}
// and here
var id: String { TTDTagDesc }
init(TTDTagDesc: String){
self.TTDTagDesc = TTDTagDesc
}
static func ==(lhs: TTDTag, rhs: TTDTag) -> Bool {
return lhs.id == rhs.id
}
}
我正在为项目列表实现标签功能。我正在尝试实现一个计算的 属性 计算项目列表中的标签集作为每个项目的不同标签集的联合,例如:
item1 - [tag1, tag2]
item2 - [tag1, tag3]
输出 > [tag1, tag2, tag3]
问题是标签 class 需要是可散列的,并且在标签的每个实例中都给出一个 UID,即使是具有相同描述的标签。因此,当我循环所有项目标签列表以创建整个列表的标签集时,结果是错误的,如:
输出 > [tag1, tag1, tag2, tag3]
代码如下:
class TTDItem: Identifiable {
var id: UUID = UUID()
var itemDesc: String
var itemTags: Set<TTDTag>
init(itemDesc: String, itemTags: Set<TTDTag>) {
self.itemDesc = itemDesc
self.itemTags = itemTags
}
}
class TTDTag: Identifiable, Hashable {
var TTDTagDesc: String
var hashValue: Int {
return id.hashValue
}
init(TTDTagDesc: String){
self.TTDTagDesc = TTDTagDesc
}
static func ==(lhs: TTDTag, rhs: TTDTag) -> Bool {
return lhs.id == rhs.id
}
}
class TTDItemList {
var itemList: [TTDItem]
init(itemList: [TTDItem]) {
self.itemList = itemList
}
//(...)
// implement computed property taglist
func itemTagsList()-> Set<TTDTag> {
var tagSet = Set<TTDTag>()
for item in self.itemList {
tagSet = tagSet.union(item.itemTags)
}
return tagSet
}
}
如何才能只访问标签描述以获得正确的结果?谢谢
这可以使用 reduce
和 union
函数来完成
func itemTagsList()-> Set<TTDTag> {
itemList.map(\.itemTags).reduce(Set<TTDTag>()){ [=10=].union() }
}
请注意,对于 Hashable
,您需要为 TTDTag
hash(into:)
func hash(into hasher: inout Hasher) {
hasher.combine(TTDTagDesc)
}
您应该 属性 名称以小写字母开头并使它们具有描述性,这样也许您可以将 TTDTagDesc
更改为 tagDescription
hashValue
已弃用(您应该已经收到警告)。您应该覆盖 hash(into:)
并在那里使用您的 TTDTagDesc
属性。
此外,您应该将 id
实现为 return TTDTagDesc
,因为这是 识别 标签的方式。
class TTDTag: Identifiable, Hashable {
var TTDTagDesc: String
// Note here
func hash(into hasher: inout Hasher) {
hasher.combine(TTDTagDesc)
}
// and here
var id: String { TTDTagDesc }
init(TTDTagDesc: String){
self.TTDTagDesc = TTDTagDesc
}
static func ==(lhs: TTDTag, rhs: TTDTag) -> Bool {
return lhs.id == rhs.id
}
}