C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
A bird is blue. We can map the string "bird" to the string "blue." This improves performance and enforces uniqueness of keys.
A solution. The map built-in provides a way to declare, with composite literal syntax, an entire table. And with a simple access we can find a value from a key (or test if a value exists).
First example. We first create a map that has string keys and string values. The key type is specified in the brackets after the "map" keyword. The value type comes afterward.
Syntax: We show the composite literal syntax in the "colors" table. We map the string "cat" to "black."
Access: We retrieve a value from the map at the key "snake." The string "green" is returned.
Based on: Golang 1.4 Golang program that uses map package main import "fmt" func main() { // Map animal names to color strings. // ... Create a map with composite literal syntax. colors := map[string]string{ "bird": "blue", "snake": "green", "cat": "black", } // Get color of snake. c := colors["snake"] // Display string. fmt.Println(c) } Output green
Add with assignment. An empty map can be created. We can then add keys and associated values imperatively (with statements) in separate lines.
Tip: In this way we can add data to a map in a loop. We must specify an empty initialization of the map.
Len: The len operator, also used on arrays and slices, can be used on a map. It counts keys (which is the same as the count of values).
Golang program that adds keys with assignments package main import "fmt" func main() { // Create an empty map. names := map[int]string{} // Add three pairs to the map in separate statements. names[990] = "file.txt" names[1009] = "data.xls" names[1209] = "image.jpg" // There are three pairs in the map. fmt.Println(len(names)) } Output 3
Delete. We can add keys to a map by assigning them. But to delete a key and its value, we must use the delete built-in: the pair is entirely erased.
Here: We add three entries to a map. The length is 3. We then delete one key and the length is reduced to 2.
Golang program that uses delete built-in package main import "fmt" func main() { // Create an empty map and add three pairs to it. ids := map[string]int{} ids["steve"] = 10 ids["mark"] = 20 ids["adnan"] = 30 fmt.Println(len(ids)) // Delete one key from it. delete(ids, "steve") fmt.Println(len(ids)) } Output 3 2
Loop over map. With the "for" and "range" keywords we can iterate over a map. We must assign variables to the two return values returned by the range expression.
Note: We can use a blank identifier (the underscore "_") to store the result of a key or value if it will not be used.
Golang program that uses for-loop on map package main import "fmt" func main() { // Create a string to string map. animals := map[string]string{} animals["cat"] = "Mittens" animals["dog"] = "Spot" // Loop over the map. for key, value := range animals { fmt.Println(key, "=", value) } } Output cat = Mittens dog = Spot
Ok syntax. A key lookup in a map returns two values: the value (if found) and a value that indicates success or failure. We often name this "success" value "ok."
Ok: In the if-statements, the ok variable is set and then tested. If true, the inner blocks are reached.
Tip: With the "comma ok" idiom, we can test for existence and store the lookup result in one statement.
Golang program that uses map, ok syntax package main import ( "fmt" ) func main() { meds := map[string]int{ "Ativan": 15, "Xanax": 20, "Klonopin": 30, } // The ok variable is set to true. if dosage, ok := meds["Xanax"]; ok { fmt.Println("Xanax", dosage) } // The ok variable is set to false. // ... The string does not exist in the map. if dosage, ok := meds["Atenolol"]; ok { fmt.Println("Atenolol", dosage) } } Output Xanax 20
Performance, map versus slice. A map accelerates lookups: it uses a special hash code to guide a search. Here I compare a map search to a slice search.
And: For both the map and the slice, we try to locate the index of the value "bird." The map has indexes as its values.
Result: The map has a clear performance advantage in this case. For larger amounts of data, this will become even greater.
Golang program that benchmarks map, slice package main import ( "fmt" "time" ) func main() { lookup := map[string]int{ "cat": 0, "dog": 1, "fish": 2, "bird": 3} values := []string{"cat", "dog", "fish", "bird"} temp := 0 t0 := time.Now() // Version 1: search map with lookup. for i := 0; i < 10000000; i++ { v, ok := lookup["bird"] if ok { temp = v } } t1 := time.Now() // Version 2: search slice with for-loop. for i := 0; i < 10000000; i++ { for x := range(values) { if values[x] == "bird" { temp = x break } } } t2 := time.Now() // Benchmark results. fmt.Println(temp) fmt.Println(t1.Sub(t0)) fmt.Println(t2.Sub(t1)) } Results 3 176.1265ms map lookup 212.1489ms slice, for-loop
A summary. We used the map built-in to link keys to values. We tested that keys exist and we retrieved the appropriate values. A map provides a clear performance win.