3 回答
TA贡献1884条经验 获得超4个赞
最简单和最灵活的方法是使用 astruct作为键类型,包括您希望成为键一部分的所有数据,因此在您的情况下:
type Key struct {
X, Y int
}
就这样。使用它:
m := map[Key]int{}
m[Key{2, 2}] = 4
m[Key{2, 3}] = 8
fmt.Println("2^2 = ", m[Key{2, 2}])
fmt.Println("2^3 = ", m[Key{2, 3}])
输出(在Go Playground上尝试):
2^2 = 4 2^3 = 8
规范:映射类型:您可以使用任何类型作为比较运算符==
和!=
完全定义的键,上面的Key
结构类型实现了这一点。
规范:比较运算符:如果结构值的所有字段都是可比较的,则结构值是可比较的。如果两个结构值对应的非空白字段相等,则它们相等。
一件重要的事情:你不应该使用指针作为键类型(例如*Key
),因为比较指针只比较内存地址,而不是指向的值。
另请注意,您也可以使用数组(不是slices)作为键类型,但数组不如结构灵活。您可以在此处阅读
这就是数组的样子:
type Key [2]int
m := map[Key]int{}
m[Key{2, 2}] = 4
m[Key{2, 3}] = 8
fmt.Println("2^2 = ", m[Key{2, 2}])
fmt.Println("2^3 = ", m[Key{2, 3}])
输出是一样的。
TA贡献2021条经验 获得超8个赞
Go 无法对一片整数进行散列。
因此,我采用的方法是将结构映射到数字。
这是一个如何做到这一点的例子:
package main
import (
"fmt"
)
type Nums struct {
num1 int
num2 int
}
func main() {
powers := make(map[Nums]int)
numbers := Nums{num1: 2, num2: 4}
powers[numbers] = 6
fmt.Printf("%v", powers[input])
}
我希望这有帮助
TA贡献1801条经验 获得超15个赞
其他答案很好地解决了您的具体问题。我想添加一个在某些极端情况下可能有用的额外技巧。
鉴于映射键必须是可比较的,您还可以使用接口。如果接口的动态值是可比较的,则接口是可比较的。
这允许您从本质上对映射进行分区,即在同一数据结构中使用多种类型的键。例如,如果您想在地图中存储 n 元组(它不适用于数组,因为数组长度是类型的一部分)。
这个想法是用一个虚拟方法定义一个接口(但它肯定不是虚拟的),并将其用作映射键:
type CompKey interface {
isCompositeKey() bool
}
var m map[CompKey]string
此时,您可以让任意类型实现接口,无论是显式实现还是仅通过嵌入实现。
在这个例子中,想法是使接口方法不被导出,这样其他结构就可以嵌入接口而不必提供实际的实现——不能从其包外部调用该方法。它只会发出该结构可用作复合映射键的信号。
type AbsoluteCoords struct {
CompKey
x, y int
}
type RelativeCoords struct {
CompKey
x, y int
}
func foo() {
p := AbsoluteCoords{x: 1, y: 2}
r := RelativeCoords{x: 10, y: 20}
m[p] = "foo"
m[r] = "bar"
fmt.Println(m[AbsoluteCoords{x: 10, y: 20}]) // "" (empty, types don't match)
fmt.Println(m[RelativeCoords{x: 10, y: 20}]) // "bar" (matches, key present)
}
当然,没有什么能阻止您在界面上声明实际的方法,这在遍历地图键时可能很有用。
这个接口键的缺点是现在你有责任确保实现类型实际上是可比较的。例如这个地图键会恐慌:
type BadKey struct {
CompKey
nonComparableSliceField []int
}
b := BadKey{nil, []int{1,2}}
m[b] = "bad!" // panic: runtime error: hash of unhashable type main.BadKey
总而言之,当您需要在同一映射中保留两组 K/V 对时,这可能是一种有趣的方法,例如,为了保持函数签名的完整性或避免定义具有 N 个非常相似的映射字段的结构。
- 3 回答
- 0 关注
- 136 浏览
添加回答
举报