Reputation: 6078
I can't find a good way to do this. I want to have a map from a list of sorted key-value pairs.
type Tag struct {
key string
value string
}
type SortedTag []Tag // sorted list of tags.
map[SortedTags]T // cannot do.
I can solve this problem by joining all the key-value pairs with a delimiter, but I feel like this is inefficient and error prone in many ways. Converting back to the key-value pair is cumbersome because we need to split the input. moreover, if the key value pair can be anything, that means we have to escape it.
If it was python, I would've stored Tag
as N-tuple of sorted 2-tupless.
If it was java, I would've created a composite object with Map<String,String>
with equals()
checking against the other hash map, hashCode()
returning the xor
of all the hashes of the map (xor
since it is commutative thus we can iterate the map in any order to compute this value).
In go, I can't think of any other good way.
Upvotes: 4
Views: 3841
Reputation: 166529
For example,
package main
import "fmt"
type Tag struct {
Key string
Value string
}
type Tags []Tag
type TagsValue struct {
// some type used as Tags value
}
type TagsMapValue struct {
Tags
TagsValue
}
type TagsMapKey string
type TagsMap map[TagsMapKey]TagsMapValue
func NewTagsMapKey(tags Tags) TagsMapKey {
b := []byte{}
for _, tag := range tags {
b = append(b, tag.Key...)
b = append(b, tag.Value...)
}
return TagsMapKey(b[:len(b)])
}
func (m *TagsMap) AddElement(tags Tags, tagsValue TagsValue) {
mapKey := NewTagsMapKey(tags)
mapValue := TagsMapValue{Tags: make(Tags, 0, len(tags)), TagsValue: tagsValue}
i := 0
for _, tag := range tags {
key := string(mapKey[i : i+len(tag.Key)])
i += len(tag.Key)
value := string(mapKey[i : i+len(tag.Value)])
i += len(tag.Value)
mapValue.Tags = append(mapValue.Tags, Tag{Key: key, Value: value})
}
(*m)[mapKey] = mapValue
return
}
func main() {
m := make(TagsMap)
sortedTags := Tags{
{Key: "key1", Value: "value1"},
{Key: "key7", Value: "value7"},
{Key: "key7", Value: "value49"},
{Key: "key42", Value: "value42"},
}
m.AddElement(sortedTags, TagsValue{})
for k, v := range m {
fmt.Println("Tags Key:", k)
fmt.Println(" Tags: ", v.Tags)
fmt.Println(" Tags Value:", v.TagsValue)
}
}
Output:
Tags Key: key1value1key7value7key7value49key42value42
Tags: [{key1 value1} {key7 value7} {key7 value49} {key42 value42}]
Tags Value: {}
If you are simply trying to test for Tags set membership,
package main
import "fmt"
type Tag struct {
Key string
Value string
}
type Tags []Tag
type TagsSetKey string
type TagsSet map[TagsSetKey]Tags
func NewTagsSetKey(tags Tags) TagsSetKey {
b := []byte{}
for _, tag := range tags {
b = append(b, tag.Key...)
b = append(b, tag.Value...)
}
return TagsSetKey(b[:len(b)])
}
func (m *TagsSet) AddElement(tags Tags) {
setKey := NewTagsSetKey(tags)
setValue := make(Tags, 0, len(tags))
i := 0
for _, tag := range tags {
key := string(setKey[i : i+len(tag.Key)])
i += len(tag.Key)
value := string(setKey[i : i+len(tag.Value)])
i += len(tag.Value)
setValue = append(setValue, Tag{Key: key, Value: value})
}
(*m)[setKey] = setValue
return
}
func (m *TagsSet) IsMember(tags Tags) bool {
return (*m)[NewTagsSetKey(tags)] != nil
}
func main() {
m := make(TagsSet)
sortedTags := Tags{
{Key: "key1", Value: "value1"},
{Key: "key7", Value: "value7"},
{Key: "key7", Value: "value49"},
{Key: "key42", Value: "value42"},
}
m.AddElement(sortedTags)
for k, v := range m {
fmt.Println("Tags Key:", k)
fmt.Println(" Tags: ", v)
}
// In set
fmt.Println(m.IsMember(sortedTags))
// Not in set
sortedTags[0].Key = "key0"
fmt.Println(m.IsMember(sortedTags))
}
Output:
Tags Key: key1value1key7value7key7value49key42value42
Tags: [{key1 value1} {key7 value7} {key7 value49} {key42 value42}]
true
false
Upvotes: 3
Reputation: 1323045
if you are after (sorted) tuples, you can check out kmanley/golang-tuple
It does have examples of sorting tuples.
This is different from deckarep/golang-set, which can also be helpful for managing those Tag
.
Upvotes: 0