在golang中使用可变长度数组作为map的键

4

我找不到一个好的方法来做这件事。我想从一个已排序的键值对列表中创建地图。

type Tag struct {
  key   string
  value string
}

type SortedTag []Tag // sorted list of tags.
map[SortedTags]T // cannot do.

我可以通过使用分隔符连接所有键值对来解决此问题,但我觉得这种方式在许多方面都是低效且容易出错的。将其转换回键值对很麻烦,因为我们需要拆分输入。此外,如果键值对可以是任何内容,那么就必须对其进行转义。
如果使用Python,我会将Tag存储为已排序的2元组的N元组。
如果是Java,我会创建一个复合对象,其中包含Map<String,String>,并使用equals()检查其他哈希映射,hashCode()返回地图所有哈希的xor(因为它是可交换的,因此我们可以以任何顺序迭代地图以计算此值)。
在Go中,我想不到其他更好的方法。

我不理解你的问题。首先,如果你想从列表中创建一个映射,那么它是否排序无关紧要。然后,我不理解你的映射类型。为什么不使用 map[string]string?最后,为什么不遍历列表中的所有元素并将它们保存到映射中呢? - akonsu
  • 我有一个排序的映射,因为我想检查键值对列表是否相等,并且在没有set类型原语时,保持按键排序是确保它们相等的最佳方法。
  • 我不希望它成为map[string]string,因为我已经列出了下面的原因。
  • 我不理解你的第三个问题。
- Jeeyoung Kim
据我理解,您不想按键搜索列表,只想检查它是否已经具有特定的键/值对,是吗?在我的第三个问题中,我假设问题是从列表构建映射。 - akonsu
3
地图使用的哈希和相等性函数是运行时的一部分,应用程序无法控制或替换这些函数。从排序后的项目中创建字符串可能是最好的选择。 - user4122236
据我所知,Maps支持可比类型的结构作为键。因此,如果我最终理解了这个问题,那么生成的Map将是map[Tag]int类型或类似的类型。基本上,这个Map的值类型并不重要,因为看起来你想要的是集合,而不是Map。 - akonsu
2个回答

3
例如,
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)
    }
}

输出:

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

如果您只是想测试标签集成员身份,
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))
}

输出:

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

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接