英文:
Keyed items in golang array initialization
问题
在Dave Cheney的酒吧问答中,我遇到了以下的结构:
a := [...]int{5, 4: 1, 0, 2: 3, 2, 1: 4}
fmt.Println(a)
输出结果为:[5 4 3 2 1 0]
这个构造似乎允许在数组的初始化字段中使用键(4: 1, 0
表示将索引为4的元素设置为1,索引为5的元素设置为0)。我以前从未见过这样的用法。它有什么用途?为什么不直接设置特定的索引呢?
英文:
In a pub quiz by Dave Cheney I came across the following construct:
a := [...]int{5, 4: 1, 0, 2: 3, 2, 1: 4}
fmt.Println(a)
>> [5 4 3 2 1 0]
It seems you can use keys in the initialization fields of an array (4: 1, 0
means set element at index 4 to 1, element at index 5 to 0). I have never seen something like this before. What is its use case? Why not set the particular index directly?
答案1
得分: 14
在复合字面量中,可以选择性地提供键(在数组和切片字面量的情况下为索引)。
对于数组和切片字面量,适用以下规则:
- 每个元素都有一个关联的整数索引,标记其在数组中的位置。
- 使用键的元素将键作为其索引;键必须是一个常量整数表达式。
- 没有键的元素使用前一个元素的索引加一。如果第一个元素没有键,则其索引为零。
元素获取未指定值的元素类型的零值。
你可以使用这个特性来:
-
更紧凑地初始化数组和切片,如果数组/切片有许多零值和少量非零值
-
在枚举元素时跳过连续的部分,并且跳过的元素将被初始化为零值
-
指定前几个元素,并且仍然指定你希望数组/切片具有的长度(最大索引+1):
a := []int{10, 20, 30, 99:0} // 指定前3个元素并将长度设置为100
规范中还包含一个示例:创建一个数组,用于判断一个字符是否是元音字母。这是一种非常简洁和直观的初始化数组的方式:
// 如果ch是元音字母,则vowels[ch]为true
vowels := [128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true}
另一个例子:让我们创建一个切片,用于判断一天是否是周末;星期一为0,星期二为1,...,星期日为6:
weekend := []bool{5: true, 6: true} // 其余的将为false
甚至更好的是,你甚至可以省略第二个索引(6
),因为它将隐式地成为6
(前一个索引+1):
weekend := []bool{5: true, true} // 其余的将为false
英文:
In composite literals the key (index in case of array and slice literals) can be optionally provided.
> For array and slice literals the following rules apply:
>
> - Each element has an associated integer index marking its position in the array.
> - An element with a key uses the key as its index; the key must be a constant integer expression.
> - An element without a key uses the previous element's index plus one. If the first element has no key, its index is zero.
Elements get the zero value of the element type whose value is not specified.
You can use this to:
-
more compactly initialize arrays and slices if the array/slice has many zero values and just a few non-zero values
-
skip ("jump over") contiguous parts when enumerating elements, and the skipped elements will be initialized with the zero values
-
specify the first couple of elements, and still specify the length (max index + 1) you want the array/slice to have:
a := []int{10, 20, 30, 99:0} // Specify first 3 elements and set length to 100
The spec also contains an example: create an array which tells if a character is a vowel. This is a very compact and talkative way to initialize the array:
// vowels[ch] is true if ch is a vowel
vowels := [128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true}
Another example: let's create a slice which tells if a day is weekend; Monday being 0, Tuesday being 1, ... and Sunday being 6:
weekend := []bool{5: true, 6: true} // The rest will be false
Or even better, you can even omit the 2nd index (6
) as it will be implicitly 6
(previous +1):
weekend := []bool{5: true, true} // The rest will be false
答案2
得分: 2
如果你的数组索引是稀疏的,那么使用{1,0,0,0,0,2,0,0,0,0,3}
等方式会更短,也比多行赋值更短,所以我猜这就是使用情况。
我以前从未在任何地方见过这种语法的使用。
英文:
If your array indices are sparse, it's shorter than doing {1,0,0,0,0,2,0,0,0,0,3}
etc, and it's shorter than multiple assignment lines, so I'm guessing that's the use case.
I've never seen this syntax used before anywhere.
答案3
得分: 0
这在同时声明和初始化数组时非常有用,特别是对于那些本来需要一个初始化函数来执行这样操作的全局变量(星期六和星期天默认为false)。
var businessDays = [7]bool{
time.Monday: true,
time.Tuesday: true,
time.Wednesday: true,
time.Thursday: true,
time.Friday: true,
}
英文:
This can be useful when declaring and initializing arrays at the same time, especially globals that would otherwise need an init function to do something like this (Saturday and Sunday default to false)
var businessDays = [7]bool{
time.Monday: true,
time.Tuesday: true,
time.Wednesday: true,
time.Thursday: true,
time.Friday: true,
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论