一组包含切片的结构体

4

我试图实现一个玩具搜索算法,需要维护一组已探索的状态。一个状态是一个结构体:

type VWState struct {
    botLocation   VWCoords
    dirtLocations []VWCoords
}

我的第一个想法是使用map[VWState]bool来实现一个简单的Set,但我似乎无法找到一种使其工作的方法。如果我尝试将VWState用作映射的键,我会得到以下恐慌:

Panic: runtime error: hash of unhashable type vw.VWState (PC=0x40EB0D)

有没有办法使这个工作?我能否为该结构实现自定义哈希函数,还是应该寻找其他实现方式?非常感谢任何帮助。
2个回答

4
您可以使用指向结构体的指针作为映射键:
map[*VWState]bool

如果你想比较等价的结构体,你可以创建一个方法来为映射输出键。使用 String() 会很方便,因为你也可以用它来打印你的结构体,或者绑定哈希函数并输出更短的内容,甚至是 int
可能只需要这么简单的代码即可,虽然你可以缩短输出内容(但要小心不要在格式行中递归调用 String() ):
func (s VWState) String() string {
    return fmt.Sprintf("%#v", s)
}

func main() {
    m := make(map[string]bool)
    s := VWState{}
    m[s.String()] = true
}

这个更改使得编译通过了,但我认为这会使用指针本身的哈希值,因此不能检测到具有相同内容的两个不同结构体实例,我的想法正确吗?如果是这样,有没有办法实现这种行为? - vlthr
是的,如果你希望等效的结构体具有相同的键,那么你需要提供一些生成该键的方式。 - JimB
你知道这种行为是否有任何工具可用于实现,以便它可以与内置的映射一起使用吗?类似于Java的hashCode()或Python的__hash __()之类的东西,还是应该使用一个 map [int] bool 并在插入之前手动提取哈希值呢? - vlthr
我添加了一个使用String()的示例。在Go中没有这样的魔法,您必须创建自己的哈希方法以输出唯一的int。但是,如果您使用完整的字符串表示,可以依靠映射实现的哈希来确保不会发生冲突。 - JimB
使用字符串表示作为键就可以解决问题了。谢谢! - vlthr

1
如果dirtLocations有一个合理的最大长度限制,那么您可以使用数组而不是切片。数组是可哈希的(前提是元素是可哈希的)。
type VWState struct {
    botLocation   VWCoords
    dirtLocations [4]VWCoords
}

你需要添加一个有效的 dirtLocations 数量计数,或者检测 VWCoords 的零值,以确定 dirtLocations 中有多少个插槽是有效的。

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