在地图中使用切片作为键

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

Slice as a key in map

问题

可以使用切片作为键吗?

这是我的尝试:

h := map[[]string]string{
  []string{"a", "b"} : "ab",
}

编译器给出了一个错误提示:invalid map key type []string。所以要么不支持使用切片作为键,要么我声明的方式不正确(如果是后者,正确的方式是什么?)。

英文:

Is it possible to use slices as keys?

There is my attempt:

h := map[[]string]string{
  []string{"a", "b"} : "ab",
}

the compiler gives me an error invalid map key type []string. So either it's not possible or I declared it incorrectly (if so, what would be a correct way?).

答案1

得分: 75

然而,可以使用数组作为映射键:

package main

import "fmt"

func main() {
    m := make(map[[2]int]bool)
    m[[2]int{1, 2}] = false
    fmt.Printf("%v", m)
}

请注意,上述代码演示了如何将数组作为映射的键使用。

英文:

However, it is possible to use arrays as map keys:

package main

import "fmt"

func main() {
    m := make(map[[2]int]bool)
    m[[2]int{1, 2}] = false
    fmt.Printf("%v", m)
}

答案2

得分: 45

不,切片不能作为映射键使用,因为它们没有定义相等性。

英文:

No, slices cannot be used as map keys as they have no equality defined.

答案3

得分: 22

Volker已经说过这是不可能的,我将提供更多详细信息,说明为什么不可能,并举一些来自规范的示例。

Map规范告诉你:

> 对于键类型的操作数,比较运算符==和!=必须完全定义;因此,键类型不能是函数、映射或切片。

它已经告诉你切片不能作为键,但你也可以在比较规范中进行检查:

> 切片、映射和函数值是不可比较的。

这意味着切片也不能作为键,但数组可以作为键。例如,你可以这样写:

h := map[[2]string]string{
  [2]string{"a", "b"} : "ab",
}
英文:

Volker already told that this is not possible and I will give a little bit more details of why is it so with examples from the spec.


Map spec tells you:

> The comparison operators == and != must be fully defined for operands
> of the key type; thus the key type must not be a function, map, or
> slice.

It already tells you that the slice can't be a key, but you could have checked it also in the comparison spec:

> Slice, map, and function values are not comparable.


This means that also slice can't be a key, an array can be a key. For example you can write:

h := map[[2]string]string{
  [2]string{"a", "b"} : "ab",
}

答案4

得分: 6

根据您的要求和数据的复杂性,您可以将字符串作为映射键,并使用切片的哈希作为映射键。

好处是您可以将此技术用于可以转换为或从字节切片转换的任何内容。

以下是将字符串切片转换为字节切片的快速方法:

[]byte(strings.Join([]string{}, ""))

以下是使用SHA1的示例:

type ByteSliceMap struct {
    buf *bytes.Buffer
    m   map[string][]byte
}

func (b *ByteSliceMap) key(buf []byte) string {
    h := sha1.New()
    h.Write(buf)
    sum := h.Sum(nil)
    return fmt.Sprintf("%x", sum)
}

func (t *ByteSliceMap) value(key []byte) (value []byte, ok bool) {
    value, ok = t.m[t.key(key)]
    return
}


func (t *ByteSliceMap) add(key, value []byte) {
    if t.m == nil {
        t.m = make(map[string][]byte)
    }
    t.m[t.key(key)] = value
}

工作版本

英文:

Depending on your requirements and the complexity of your data, you could use a string as a map key and then use a hash of your slice as the map key.

The nice thing is you can use this technique with anything that can be converted to or from a slice of bytes.

Here's a quick way to convert your slice of strings into a slice of bytes:

[]byte(strings.Join([]string{},""))

Here's an example using SHA1:

type ByteSliceMap struct {
	buf *bytes.Buffer
	m   map[string][]byte
}

func (b *ByteSliceMap) key(buf []byte) string {
	h := sha1.New()
	h.Write(buf)
	sum := h.Sum(nil)
	return fmt.Sprintf("%x", sum)
}

func (t *ByteSliceMap) value(key []byte) (value []byte, ok bool) {
	value, ok = t.m[t.key(key)]
	return
}


func (t *ByteSliceMap) add(key, value []byte) {
	if t.m == nil {
		t.m = make(map[string][]byte)
	}
	t.m[t.key(key)] = value
}

Working version

答案5

得分: 3

解决这个问题的一种方法是从具有明确定义的比较运算符的切片中实际创建一个键:

func createKey(s []string) string { return fmt.Sprintf("%q", s) }

m := make(map[string]string)
s := []string{"a","b"}
m[createKey(s)] = "myValue"

以类似的方式,您需要创建用于创建与字符串类型不同的切片的键的函数。

英文:

One way to get around this problem is to actually create a key from a slice which has well defined comparison operators:

func createKey(s []string) string { return fmt.Sprintf("%q", s) }

m := make(map[string]string)
s := []string{"a","b"}
m[createKey(s)] = "myValue"

In a similar fashion you would have to create functions for creating keys of slices with type different to string.

huangapple
  • 本文由 发表于 2013年11月30日 14:51:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/20297503.html
匿名

发表评论

匿名网友

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

确定