![](/img/trans.png)
[英]missing type in composite literal go AND missing key in map literal go
[英]How to make composite key for a hash map in go
首先,我對復合鍵的定義 - 兩個或更多的值組合成鍵。 不要與數據庫中的復合鍵混淆。
我的目標是將pow(x, y)
計算值保存在哈希表中,其中x
和y
是整數。 這是我需要關於如何制作密鑰的想法的地方,以便給定x
和y
,我可以在哈希表中查找它,以找到pow(x,y)
。
例如:
pow(2, 3) => {key(2,3):8}
我想弄清楚的是如何獲取對(2,3)
的映射鍵,即生成由多個值組合而成的鍵的最佳方法,並在哈希表中使用它。
最簡單,最靈活的方法是使用struct
作為鍵類型,包括您希望成為鍵的一部分的所有數據,因此在您的情況下:
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
結構類型實現了這一點。
規范:比較運算符:如果所有字段都具有可比性,則結構值可比較。 如果相應的非空白字段相等,則兩個結構值相等。
一個重要的事情是:你不應該使用指針作為鍵類型(例如*Key
),因為比較指針只比較內存地址,而不是指向的值。
另請注意,您也可以使用數組 (而不是切片 )作為鍵類型,但數組不像結構一樣靈活。 你可以在這里閱讀更多相關內容: 為什么Go中的數組?
這就是數組的樣子:
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}])
輸出是一樣的。 在Go Playground嘗試一下。
Go無法對一片int進行哈希處理。
因此,我接近這個的方法是將結構映射到數字。
以下是如何完成此操作的示例:
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])
}
我希望有所幫助
其他答案很好地解決了您的具體問題。 我想添加一個在某些極端情況下可能有用的額外技巧。
鑒於映射鍵必須具有可比性,您還可以使用接口。 如果它們的動態值具有可比性,則接口具有可比性。
這允許您從本質上對映射進行分區,即在同一數據結構中使用多種類型的鍵。 例如,如果您想在映射中存儲 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 個非常相似的映射字段的結構。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.