在Go语言中使用可变长度数组作为映射键

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

Using variable-length array as a map key in golang

问题

我找不到一个好的方法来做这个。我想要从一个排序的键值对列表创建一个映射。

type Tag struct {
  key   string
  value string
}

type SortedTag []Tag // 排序的标签列表
map[SortedTags]T // 无法实现

我可以通过使用分隔符连接所有的键值对来解决这个问题,但我觉得这种方法在很多方面都是低效和容易出错的。将其转换回键值对很麻烦,因为我们需要拆分输入。此外,如果键值对可以是任意值,那么我们就需要进行转义。

如果是在Python中,我会将Tag存储为排序的2元组的N元组。

如果是在Java中,我会创建一个复合对象,其中包含Map<String, String>,并使用equals()方法与其他哈希映射进行比较,hashCode()方法返回映射的所有哈希值的异或值(使用异或是因为它是可交换的,因此我们可以以任意顺序迭代映射来计算这个值)。

在Go中,我想不到其他好的方法。

英文:

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&lt;String,String&gt; 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.

答案1

得分: 3

例如,

package main

import "fmt"

type Tag struct {
    Key   string
    Value string
}

type Tags []Tag

type TagsValue struct {
    // 作为 Tags 值的某些类型
}

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

输出:

Tags Key: key1value1key7value7key7value49key42value42
   Tags:       [{key1 value1} {key7 value7} {key7 value49} {key42 value42}]
   Tags Value: {}

如果你只是想测试 Tags 是否属于集合,

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)
    }
    // 在集合中
    fmt.Println(m.IsMember(sortedTags))
    // 不在集合中
    sortedTags[0].Key = "key0"
    fmt.Println(m.IsMember(sortedTags))
}

输出:

Tags Key: key1value1key7value7key7value49key42value42
   Tags:  [{key1 value1} {key7 value7} {key7 value49} {key42 value42}]
true
false
英文:

For example,

package main

import &quot;fmt&quot;

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: &quot;key1&quot;, Value: &quot;value1&quot;},
		{Key: &quot;key7&quot;, Value: &quot;value7&quot;},
		{Key: &quot;key7&quot;, Value: &quot;value49&quot;},
		{Key: &quot;key42&quot;, Value: &quot;value42&quot;},
	}
	m.AddElement(sortedTags, TagsValue{})
	for k, v := range m {
		fmt.Println(&quot;Tags Key:&quot;, k)
		fmt.Println(&quot;   Tags:      &quot;, v.Tags)
		fmt.Println(&quot;   Tags Value:&quot;, 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 &quot;fmt&quot;

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: &quot;key1&quot;, Value: &quot;value1&quot;},
		{Key: &quot;key7&quot;, Value: &quot;value7&quot;},
		{Key: &quot;key7&quot;, Value: &quot;value49&quot;},
		{Key: &quot;key42&quot;, Value: &quot;value42&quot;},
	}
	m.AddElement(sortedTags)
	for k, v := range m {
		fmt.Println(&quot;Tags Key:&quot;, k)
		fmt.Println(&quot;   Tags: &quot;, v)
	}
	// In set
	fmt.Println(m.IsMember(sortedTags))
	// Not in set
	sortedTags[0].Key = &quot;key0&quot;
	fmt.Println(m.IsMember(sortedTags))
}

Output:

Tags Key: key1value1key7value7key7value49key42value42
   Tags:  [{key1 value1} {key7 value7} {key7 value49} {key42 value42}]
true
false

答案2

得分: 0

如果你想要(排序的)元组,你可以查看kmanley/golang-tuple

它有排序元组的示例

这与deckarep/golang-set不同,后者对于管理那些Tag也很有帮助。

英文:

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.

huangapple
  • 本文由 发表于 2014年10月25日 13:20:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/26559568.html
匿名

发表评论

匿名网友

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

确定