Initializing a Go map in a single statement

huangapple go评论84阅读模式
英文:

Initializing a Go map in a single statement

问题

这是我的代码:

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"

我可以用一条语句或一行代码完成同样的操作吗?

英文:

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?

答案1

得分: 113

是的,你可以使用一个语句(在规范中称为复合字面量)来创建一个映射:

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

或者,如果你在函数内部,你可以使用短变量声明

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

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",
}

答案2

得分: 8

当键和值之间存在逻辑关系时,你也可以使用循环来初始化映射。将逻辑放入循环体中。这种方法可能比使用列举所有键值对的复合字面量要简洁得多,特别是当键值对的数量很大时。

你的示例可以用以下代码实现:

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

输出结果(在Go Playground上尝试):

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

这是另一种实现方式(使用不同的逻辑实现):

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)

输出结果相同。在Go Playground上尝试这个变体。

还有更多的解决方案,这次只展示循环体部分(Playground链接:另一个 #1另一个 #2):

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

另一种方法是使用两个嵌套的循环来生成值,并根据值计算键:

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

Go Playground上尝试这个方法。

如果值的数量不多,另一种可行的方法是将所有元素枚举为一个string值,并使用子切片(由于不会创建新的支持数组,因此效率很高,字符串的支持数组是共享的):

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)

输出结果(在Go Playground上尝试):

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

还要注意,如果键的类型是int,并且键的集合(或多或少)是连续的,通常使用切片而不是映射更高效(无论是内存还是性能方面):

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)

输出结果(在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"]

正如你在第三个示例m3中看到的,你可以在复合字面量中使用可选索引来指定后面的值的索引。关于这个问题可以参考这里:https://stackoverflow.com/questions/36302441/keyed-items-in-golang-array-initialization/36302875#36302875

英文:

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 &lt; 9; i++ {
	m[i+1] = string(&quot;abc&quot;[i/3]) + string(&quot;abc&quot;[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 &lt; 9; i++ {
	m[i+1] = &quot;abc&quot;[i/3:i/3+1] + &quot;abc&quot;[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(&quot;%c%c&quot;, &quot;abc&quot;[i/3], &quot;abc&quot;[i%3])
// Another #2:
m[i+1] = fmt.Sprintf(&quot;%c%c&quot;, &#39;a&#39;+i/3, &#39;a&#39;+i%3)

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

for i := &#39;a&#39;; i &lt;= &#39;c&#39;; i++ {
	for j := &#39;a&#39;; j &lt;= &#39;c&#39;; j++ {
		m[int((i-&#39;a&#39;)*3+j-&#39;a&#39;+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 = &quot;aaabacbabbbccacbcc&quot;

m := map[int]string{}
for i := 0; i &lt; 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 &lt; 9; i++ {
	m[i+1] = fmt.Sprintf(&quot;%c%c&quot;, &#39;a&#39;+i/3, &#39;a&#39;+i%3)
}
fmt.Printf(&quot;%q\n&quot;, m)

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

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

Output (try it on the Go Playground):

[&quot;&quot; &quot;aa&quot; &quot;ab&quot; &quot;ac&quot; &quot;ba&quot; &quot;bb&quot; &quot;bc&quot; &quot;ca&quot; &quot;cb&quot; &quot;cc&quot;]
[&quot;&quot; &quot;aa&quot; &quot;ab&quot; &quot;ac&quot; &quot;ba&quot; &quot;bb&quot; &quot;bc&quot; &quot;ca&quot; &quot;cb&quot; &quot;cc&quot;]
[&quot;&quot; &quot;aa&quot; &quot;ab&quot; &quot;ac&quot; &quot;ba&quot; &quot;bb&quot; &quot;bc&quot; &quot;ca&quot; &quot;cb&quot; &quot;cc&quot;]

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: https://stackoverflow.com/questions/36302441/keyed-items-in-golang-array-initialization/36302875#36302875

答案3

得分: 1

我首选的方法是使用复合字面量和短变量声明。在某些情况下,使用函数可以减少混乱。

package main

import (
	"fmt"
)

// initMap用于初始化一个以整数为键的映射,从1开始
func initMap(sa []string) map[int]string {
    m := make(map[int]string, len(sa))
	for k, v := range sa {
        m[k+1] = v // 将k加1,因为它从0开始
	}
	return m
}

// main是任何Go应用程序的入口点
func main() {
	// 我首选的方法是使用复合字面量和短变量声明
	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)

	// 使用函数来初始化映射可能有助于避免混乱
	keys2 := initMap([]string{"aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"})
	fmt.Println(keys2)
}

在此处查看实际运行效果:https://play.golang.org/p/Rrb9ChBkXW

英文:

My preferred approach is a composite literal in a short variable declaration. In some cases a function might help to reduce clutter.

package main

import (
	&quot;fmt&quot;
)

// 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: &quot;aa&quot;, 2: &quot;ab&quot;, 3: &quot;ac&quot;, 4: &quot;ba&quot;, 5: &quot;bb&quot;, 6: &quot;bc&quot;, 7: &quot;ca&quot;, 8: &quot;cb&quot;, 9: &quot;cc&quot;}
	fmt.Println(keys)

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

See it in action at https://play.golang.org/p/Rrb9ChBkXW

huangapple
  • 本文由 发表于 2016年12月11日 01:29:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/41078272.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定