当键和值之间存在逻辑时,您还可以使用循环来初始化映射。将逻辑“放入”循环体中。这可能比使用composite literal 枚举所有键值对要短得多,尤其是在键值对的数量很大的情况下。
你的例子可以用这个来实现:
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 上试试这个变体。
还有更多解决方案,现在只发布循环体(游乐场链接: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)
另一种方法可能会使用 2 个循环(嵌入式)来生成值,并根据值计算键:
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 中看到的那样,您可以在复合文字中使用可选索引来指定后面值的索引。更多信息在这里:Keyed items in golang array initialization