mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-12-17 11:14:20 +08:00
@@ -2,7 +2,7 @@
|
||||
|
||||
哈希表是一種巧妙併且實用的數據結構。它是一個無序的key/value對的集合,其中所有的key都是不同的,然後通過給定的key可以在常數時間複雜度內檢索、更新或刪除對應的value。
|
||||
|
||||
在Go語言中,一個map就是一個哈希表的引用,map類型可以寫爲map[K]V,其中K和V分别對應key和value。map中所有的key都有相同的類型,所以的value也有着相同的類型,但是key和value之間可以是不同的數據類型。其中K對應的key必鬚是支持==比較運算符的數據類型,所以map可以通過測試key是否相等來判斷是否已經存在。雖然浮點數類型也是支持相等運算符比較的,但是將浮點數用做key類型則是一個壞的想法,正如第三章提到的,最壞的情況是可能出現的NaN和任何浮點數都不相等。對於V對應的value數據類型則沒有任何的限製。
|
||||
在Go語言中,一個map就是一個哈希表的引用,map類型可以寫爲map[K]V,其中K和V分别對應key和value。map中所有的key都有相同的類型,所以的value也有着相同的類型,但是key和value之間可以是不同的數據類型。其中K對應的key必須是支持==比較運算符的數據類型,所以map可以通過測試key是否相等來判斷是否已經存在。雖然浮點數類型也是支持相等運算符比較的,但是將浮點數用做key類型則是一個壞的想法,正如第三章提到的,最壞的情況是可能出現的NaN和任何浮點數都不相等。對於V對應的value數據類型則沒有任何的限製。
|
||||
|
||||
內置的make函數可以創建一個map:
|
||||
|
||||
@@ -76,7 +76,7 @@ for name, age := range ages {
|
||||
}
|
||||
```
|
||||
|
||||
Map的迭代順序是不確定的,併且不同的哈希函數實現可能導致不同的遍歷順序。在實踐中,遍歷的順序是隨機的,每一次遍歷的順序都不相同。這是故意的,每次都使用隨機的遍歷順序可以強製要求程序不會依賴具體的哈希函數實現。如果要按順序遍歷key/value對,我們必鬚顯式地對key進行排序,可以使用sort包的Strings函數對字符串slice進行排序。下面是常見的處理方式:
|
||||
Map的迭代順序是不確定的,併且不同的哈希函數實現可能導致不同的遍歷順序。在實踐中,遍歷的順序是隨機的,每一次遍歷的順序都不相同。這是故意的,每次都使用隨機的遍歷順序可以強製要求程序不會依賴具體的哈希函數實現。如果要按順序遍歷key/value對,我們必須顯式地對key進行排序,可以使用sort包的Strings函數對字符串slice進行排序。下面是常見的處理方式:
|
||||
|
||||
```Go
|
||||
import "sort"
|
||||
@@ -113,7 +113,7 @@ map上的大部分操作,包括査找、刪除、len和range循環都可以安
|
||||
ages["carol"] = 21 // panic: assignment to entry in nil map
|
||||
```
|
||||
|
||||
在向map存數據前必鬚先創建map。
|
||||
在向map存數據前必須先創建map。
|
||||
|
||||
通過key作爲索引下標來訪問map將産生一個value。如果key在map中是存在的,那麽將得到與key對應的value;如果key不存在,那麽將得到value對應類型的零值,正如我們前面看到的ages["bob"]那樣。這個規則很實用,但是有時候可能需要知道對應的元素是否眞的是在map之中。例如,如果元素類型是一個數字,你可以需要區分一個已經存在的0,和不存在而返迴零值的0,可以像下面這樣測試:
|
||||
|
||||
@@ -130,7 +130,7 @@ if age, ok := ages["bob"]; !ok { /* ... */ }
|
||||
|
||||
在這種場景下,map的下標語法將産生兩個值;第二個是一個布爾值,用於報告元素是否眞的存在。布爾變量一般命名爲ok,特别適合馬上用於if條件判斷部分。
|
||||
|
||||
和slice一樣,map之間也不能進行相等比較;唯一的例外是和nil進行比較。要判斷兩個map是否包含相同的key和value,我們必鬚通過一個循環實現:
|
||||
和slice一樣,map之間也不能進行相等比較;唯一的例外是和nil進行比較。要判斷兩個map是否包含相同的key和value,我們必須通過一個循環實現:
|
||||
|
||||
```Go
|
||||
func equal(x, y map[string]int) bool {
|
||||
@@ -178,7 +178,7 @@ func main() {
|
||||
|
||||
Go程序員將這種忽略value的map當作一個字符串集合,併非所有`map[string]bool`類型value都是無關緊要的;有一些則可能會同時包含tue和false的值。
|
||||
|
||||
有時候我們需要一個map或set的key是slice類型,但是map的key必鬚是可比較的類型,但是slice併不滿足這個條件。不過,我們可以通過兩個步驟繞過這個限製。第一步,定義一個輔助函數k,將slice轉爲map對應的string類型的key,確保隻有x和y相等時k(x) == k(y)才成立。然後創建一個key爲string類型的map,在每次對map操作時先用k輔助函數將slice轉化爲string類型。
|
||||
有時候我們需要一個map或set的key是slice類型,但是map的key必須是可比較的類型,但是slice併不滿足這個條件。不過,我們可以通過兩個步驟繞過這個限製。第一步,定義一個輔助函數k,將slice轉爲map對應的string類型的key,確保隻有x和y相等時k(x) == k(y)才成立。然後創建一個key爲string類型的map,在每次對map操作時先用k輔助函數將slice轉化爲string類型。
|
||||
|
||||
下面的例子演示了如何使用map來記録提交相同的字符串列表的次數。它使用了fmt.Sprintf函數將字符串列表轉換爲一個字符串以用於map的key,通過%q參數忠實地記録每個字符串元素的信息:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user