web-dev-qa-db-fra.com

Comment puis-je initier une carte de golang en une instruction?

Ceci est mon code:

var keys map[int]string
keys = make(map[int]string)

keys[1] = "aa"
keys[2] = "ab"
keys[3] = "ac"
keys[4] = "ba"
keys[5] = "bb"
keys[6] = "bc"
keys[7] = "ca"
keys[8] = "cb"
keys[9] = "cc"

Puis-je faire la même chose en une déclaration et/ou en une ligne?

8
sensorario

Oui, vous pouvez créer une carte avec une seule instruction (appelée littéral composite dans la spécification): 

var keys = map[int]string{
    1: "aa",
    2: "ab",
    3: "ac",
    4: "ba",
    5: "bb",
    6: "bc",
    7: "ca",
    8: "cb",
    9: "cc",
}

Ou, si vous êtes à l'intérieur d'une fonction, vous pouvez utiliser une déclaration de variable short :

keys := map[int]string{
    1: "aa",
    2: "ab",
    3: "ac",
    4: "ba",
    5: "bb",
    6: "bc",
    7: "ca",
    8: "cb",
    9: "cc",
}
33
Tim Cooper

Lorsqu'il existe une logique entre les clés et les valeurs, vous pouvez également utiliser une boucle pour initialiser la carte. "Mettez" la logique dans le corps de la boucle. Cela peut être beaucoup plus court que d'utiliser un composite literal énumérant toutes les paires clé-valeur, en particulier si le nombre de paires clé-valeur est grand.

Votre exemple peut être implémenté avec ceci:

m := map[int]string{}
for i := 0; i < 9; i++ {
    m[i+1] = string("abc"[i/3]) + string("abc"[i%3])
}
fmt.Println(m)

Sortie (essayez-le sur Go Playground ):

map[5:bb 8:cb 4:ba 2:ab 3:ac 6:bc 7:ca 9:cc 1:aa]

Une variante de cette solution (utilisant une implémentation logique différente):

m := map[int]string{}
for i := 0; i < 9; i++ {
    m[i+1] = "abc"[i/3:i/3+1] + "abc"[i%3:i%3+1]
}
fmt.Println(m)

La sortie est la même. Essayez cette variante sur le Go Playground .

Et encore plus de solutions, en affichant maintenant uniquement le corps de la boucle (liens Playground: autre n ° 1 , autre n ° 2 ):

// Another #1:
m[i+1] = fmt.Sprintf("%c%c", "abc"[i/3], "abc"[i%3])
// Another #2:
m[i+1] = fmt.Sprintf("%c%c", 'a'+i/3, 'a'+i%3)

Une approche différente peut utiliser 2 boucles (intégrées) qui génèrent la valeur et calcule la clé à partir de la valeur:

for i := 'a'; i <= 'c'; i++ {
    for j := 'a'; j <= 'c'; j++ {
        m[int((i-'a')*3+j-'a'+1)] = string(i) + string(j)
    }
}

Essayez ceci sur le Go Playground .

Si le nombre de valeurs n'est pas grand, une autre approche viable peut être d'énumérer tous les éléments dans une valeur string et d'utiliser le sous-découpage (efficace car aucune nouvelle matrice de sauvegarde ne sera créée, le tableau de sauvegarde des chaînes est partagé):

const s = "aaabacbabbbccacbcc"

m := map[int]string{}
for i := 0; i < 9; i++ {
    m[i+1] = s[i*2 : i*2+2]
}
fmt.Println(m)

Sortie (essayez ceci sur le Go Playground ):

map[9:cc 1:aa 2:ab 5:bb 8:cb 3:ac 4:ba 6:bc 7:ca]

Notez également que si la clé est de type int et que l'ensemble de clés est (plus ou moins) contigu, il est souvent plus efficace (à la fois en termes de mémoire et de performances) d'utiliser une tranche:

m := make([]string, 10)
for i := 0; i < 9; i++ {
    m[i+1] = fmt.Sprintf("%c%c", 'a'+i/3, 'a'+i%3)
}
fmt.Printf("%q\n", m)

m2 := []string{"", "aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"}
fmt.Printf("%q\n", m2)

m3 := []string{1: "aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"}
fmt.Printf("%q\n", m3)

Sortie (essayez-le sur Go Playground ):

["" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc"]
["" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc"]
["" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc"]

Comme vous pouvez le voir dans le troisième exemple m3, vous pouvez utiliser des index facultatifs dans le littéral composite pour spécifier l'index de la valeur suivante. Plus d'informations à ce sujet ici: Eléments à clé dans l'initialisation d'un tableau golang

7
icza

Mon approche préférée est un littéral composite dans une déclaration de variable courte. Dans certains cas, une fonction peut aider à réduire l'encombrement. 

package main

import (
    "fmt"
)

// initMap initializes a map with an integer key starting at 1
func initMap(sa []string) map[int]string {
    m := make(map[int]string, len(sa))
    for k, v := range sa {
        m[k+1] = v // add 1 to k as it is starting at base 0
    }
    return m
}

// main is the entry point of any go application
func main() {
    // My preferred approach is a composite literal in a short variable declaration
    keys := map[int]string{1: "aa", 2: "ab", 3: "ac", 4: "ba", 5: "bb", 6: "bc", 7: "ca", 8: "cb", 9: "cc"}
    fmt.Println(keys)

    // Using a function to initialize the map might help to avoid clutter
    keys2 := initMap([]string{"aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"})
    fmt.Println(keys2)
}

Voyez-le en action sur https://play.golang.org/p/Rrb9ChBkXW

1
Peter Gloor