I'm implementing a tag feature for an item list. I'm trying implementing a computed property that calculate the tag set in a list of item as the union of different tag set of each item like:
item1 - [tag1, tag2]
item2 - [tag1, tag3]
output > [tag1, tag2, tag3]
The problem is that the Tag class need to be hashable and an UID is given at each instance of the tag, even tag with the same description. So when I loop in all the item taglist to create the tag set of the whole list the results is wrong like:
output > [tag1, tag1, tag2, tag3]
Here's the code:
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
}
}
How can I access only to the tag description in order to obtain the correct result? Thanks
CodePudding user response:
This can be done using reduce
and the union
function
func itemTagsList()-> Set<TTDTag> {
itemList.map(\.itemTags).reduce(Set<TTDTag>()){ $0.union($1) }
}
Note that for Hashable
you need to implement hash(into:)
for TTDTag
func hash(into hasher: inout Hasher) {
hasher.combine(TTDTagDesc)
}
You should start property names with a lowercase letter and make them descriptive so maybe you could change TTDTagDesc
to tagDescription
CodePudding user response:
hashValue
is deprecated (and you should have received a warning for this). You should override hash(into:)
and use your TTDTagDesc
property there.
Also, you should implement id
to return TTDTagDesc
, because that is what identifies a tag.
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
}
}