Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing a Go map in a single statement

This is my 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" 

Can I do the same thing in one statement and/or in one line?

like image 234
sensorario Avatar asked Dec 10 '16 17:12

sensorario


People also ask

How do you initialize a map in Go?

Initializing map using map literals: Map literal is the easiest way to initialize a map with data just simply separate the key-value pair with a colon and the last trailing colon is necessary if you do not use, then the compiler will give an error.

How do I create a constant map in Golang?

You can not create constants of maps, arrays and it is written in effective go: Constants in Go are just that—constant. They are created at compile time, even when defined as locals in functions, and can only be numbers, characters (runes), strings or booleans.

How does one declare and initialize a map of size 0?

map's default constructor creates empty map. You may increase map's size only by inserting elements (like m["str1"]=0 or m. insert(std::map<std::string,int>::value_type("str2",0)) ).


2 Answers

Yes, you can create a map with a single statement (called a composite literal in the spec):

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

Or, if you are inside of a function, you can use 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", } 
like image 172
Tim Cooper Avatar answered Oct 29 '22 04:10

Tim Cooper


When there is logic between keys and values, you may also use a loop to initialize the map. "Put" the logic into the loop body. This may be significantly shorter than using a composite literal enumerating all key-value pairs, especially if the number of key-value pairs is big.

Your example can be implemented with this:

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

Output (try it on the Go Playground):

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

A variant of this solution (using a different logic implementation):

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) 

Output is the "same". Try this variant on the Go Playground.

And even more solutions, now posting only the loop body (Playground links: another #1, another #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) 

A different approach might use 2 loops (embedded) which generate the value, and calculates the key from the value:

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

Try this on the Go Playground.

If the number of values is not big, another viable approach can be to enumerate all the elements in one string value, and use subslicing (which is efficient as no new backing arrays will be created, the backing array of the strings is shared):

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) 

Output (try this on the Go Playground):

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

Also note that if the key is of type int and the set of keys is (more or less) contiguous, often it is more efficient (both memory and performance-wise) to use a slice instead:

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) 

Output (try it on the 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"] 

As you can see in the third example m3, you can use optional indices in the composite literal to specify the index of the value following. More about this here: Keyed items in golang array initialization

like image 42
icza Avatar answered Oct 29 '22 03:10

icza