Cvičení – použití map

Dokončeno

Mapa v Go je v podstatě hashovací tabulka, což je kolekce párů klíč-hodnota. Všechny klíče v mapě musí být stejného typu, a proto hodnoty. Pro klíče a hodnoty ale můžete použít různé typy. Například klíče můžou být čísla a hodnoty můžou být řetězce. Pokud chcete získat přístup k určité položce v mapě, odkazujete na jeho klíč.

Deklarace a inicializace mapy

Pokud chcete deklarovat mapu, musíte použít map klíčové slovo. Pak definujete klíč a typ hodnoty, například takto: map[T]T. Pokud například chcete vytvořit mapu obsahující věk studentů, můžete použít následující kód:

package main

import "fmt"

func main() {
    studentsAge := map[string]int{
        "john": 32,
        "bob":  31,
    }
    fmt.Println(studentsAge)
}

Při spuštění předchozího kódu se zobrazí následující výstup:

map[bob:31 john:32]

Pokud nechcete inicializovat mapu s položkami, můžete pomocí integrované make() funkce vytvořit mapu v předchozí části. K vytvoření prázdné mapy můžete použít následující kód:

studentsAge := make(map[string]int)

Mapy jsou dynamické. Po jejich vytvoření můžete přidávat, přistupovat k nim nebo je odebírat. Pojďme se na tyto akce podívat.

Přidat položky

Pokud chcete přidat položky, nemusíte používat předdefinované funkce, jako to děláte s řezy. Mapy jsou jednodušší. Stačí definovat klíč a hodnotu. Pokud pár neexistuje, položka se přidá do mapy.

Pojďme přepsat kód, který jsme použili dříve k vytvoření mapy pomocí make funkce. Pak přidáme položky do mapy. Můžete použít následující kód:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println(studentsAge)
}

Při spuštění kódu získáte stejný výstup jako předtím:

map[bob:31 john:32]

Všimněte si, že jsme přidali položky do mapy, která byla inicializována. Pokud se ale pokusíte provést totéž s mapou nil , zobrazí se chyba. Například následující kód nebude fungovat:

package main

import "fmt"

func main() {
    var studentsAge map[string]int
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println(studentsAge)
}

Při spuštění předchozího kódu se zobrazí následující chyba:

panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()
        /Users/johndoe/go/src/helloworld/main.go:7 +0x4f
exit status 2

Abyste se vyhnuli problémům při přidávání položek do mapy, ujistěte se, že vytvoříte prázdnou mapu (ne nil mapu) pomocí make funkce, jako jsme ukázali v předchozím fragmentu kódu. Toto pravidlo platí jenom při přidávání položek. Pokud spustíte operace vyhledávání, odstranění nebo smyčky na mapě nil , Go nebude panice. Toto chování potvrdíme za chvíli.

Přístup k položkám

Pokud chcete získat přístup k položkám v mapě, použijte obvyklý zápis dolního indexu m[key], jako je tomu u polí nebo řezů. Tady je jednoduchý příklad přístupu k položce:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println("Bob's age is", studentsAge["bob"])
}

Při použití zápisu dolního indexu v mapě se vždy vrátí odpověď, i když klíč není na mapě. Při přístupu k položce, která neexistuje, nejde přejít k panice. Místo toho se vrátí výchozí hodnota. Toto chování můžete potvrdit pomocí následujícího kódu:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    fmt.Println("Christy's age is", studentsAge["christy"])
}

Při spuštění předchozího kódu se zobrazí následující výstup:

Christy's age is 0

V mnoha případech je spravedlivé, že Go nevrátí chybu, když přistupujete k položce, která v mapě neexistuje. Někdy ale potřebujete vědět, jestli položka existuje nebo ne. Zápis dolního indexu pro mapu může v go přinést dvě hodnoty. První je hodnota položky. Druhým příznakem je logický příznak, který označuje, jestli klíč existuje nebo ne.

K vyřešení problému s posledním fragmentem kódu můžete použít následující kód:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    age, exist := studentsAge["christy"]
    if exist {
        fmt.Println("Christy's age is", age)
    } else {
        fmt.Println("Christy's age couldn't be found")
    }
}

Při spuštění předchozího kódu se zobrazí následující výstup:

Christy's age couldn't be found

Pomocí druhého fragmentu kódu zkontrolujte, jestli klíč v mapě existuje, než k němu přistupujete.

Odebrání položek

Pokud chcete odebrat položku z mapy, použijte integrovanou delete() funkci. Tady je příklad odebrání položek z mapy:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    delete(studentsAge, "john")
    fmt.Println(studentsAge)
}

Při spuštění kódu získáte následující výstup:

map[bob:31]

Jak jsme řekli dříve, pokud se pokusíte odstranit položku, která neexistuje, Go nebude panice. Tady je příklad tohoto chování:

package main

import "fmt"

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    delete(studentsAge, "christy")
    fmt.Println(studentsAge)
}

Při spuštění kódu se nezobrazí chyba a zobrazí se následující výstup:

map[bob:31 john:32]

Smyčka v mapě

Nakonec se podíváme, jak můžete v mapě smyčce získat přístup ke všem položkám prostřednictvím kódu programu. K tomu můžete použít smyčku založenou na rozsahu, například v tomto příkladu:

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31
    for name, age := range studentsAge {
        fmt.Printf("%s\t%d\n", name, age)
    }
}

Při spuštění předchozího kódu se zobrazí následující výstup:

john    32
bob     31

Všimněte si, jak můžete uložit informace o klíči a hodnotě v různých proměnných. V tomto případě držíme klíč v name proměnné a hodnotu v age proměnné. range Získá tedy první klíč položky a druhou hodnotu této položky. Některou z nich můžete ignorovat pomocí proměnné, například v tomto příkladu _ :

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    for _, age := range studentsAge {
        fmt.Printf("Ages %d\n", age)
    }
}

I když v tomto případě nemá smysl tisknout věky tímto způsobem, budou existovat případy, kdy nepotřebujete znát klíč položky. Alternativně můžete použít jenom klíč položky, například tento příklad:

package main

import (
    "fmt"
)

func main() {
    studentsAge := make(map[string]int)
    studentsAge["john"] = 32
    studentsAge["bob"] = 31

    for name := range studentsAge {
        fmt.Printf("Names %s\n", name)
    }
}