英文:
Get only the initialized content from a slice
问题
我将为您翻译以下内容:
我将一个未知数量的项目(大约10,000个)添加到一个切片中。
le := 500
l := make([]string, le)
l = append(l, "a")
l = append(l, "b")
l = append(l, "c")
l = append(l, "d")
l = append(l, "...")
然后,我的切片包含以下内容:
i:0-v:
...
i:500-v:a
i:501-v:b
i:502-v:c
i:503-v:d
i:504-v:e
我正在寻找一种方法,只获取存储在切片中的已初始化项目。我想要去掉i:0-v:
到i:499-v:
之间的部分。
我可以通过重新切片l
来获得所需的结果,以删除切片的前几个元素(前几个元素的数量取决于传递给make
方法的length
参数)。
l = l[le:]
for j, k := range l{
fmt.Printf("i:%d-v:%s\n", j, k)
}
我的问题是:这是实现这一目标的正确方法吗?还是有更好的方法来去除在添加过程中未初始化的项目?
英文:
I append an unknown number of items (arround 10.000) into a slice
le := 500
l := make([]string, le)
l = append(l, "a")
l = append(l, "b")
l = append(l, "c")
l = append(l, "d")
l = append(l, "...")
for i, v := range l{
fmt.Printf("i:%d-v:%s\n", i, v)
}
After this my slide contains
i:0-v:
...
i:500-v:a
i:501-v:b
i:502-v:c
i:503-v:d
i:504-v:e
I'm looking for a way to get only the initialized items stored in the slice.
I want to be rid of i:0-v:
to i:499-v:
I can get the desired result re-slicing l
, to remove the first elements of the slice (the number of first elements dépends on the length
parameter passed to the make
method).
l = l[le:]
for j, k := range l{
fmt.Printf("i:%d-v:%s\n", j, k)
}
My question is: Is it the right way to achieve this or is there a nicer way to get rid of the items not initialized, added during the append?
答案1
得分: 3
为什么不创建一个空的切片,
// 创建一个长度为0的切片
l := []string{}
l = append(l, "a")
l = append(l, "b")
l = append(l, "c")
l = append(l, "d")
l = append(l, "...")
将会输出,
i:0-v:a
i:1-v:b
i:2-v:c
i:3-v:d
i:4-v:...
英文:
Why not make an empty slice,
// create a slice with len 0
l := []string{}
l = append(l, "a")
l = append(l, "b")
l = append(l, "c")
l = append(l, "d")
l = append(l, "...")
will give an output,
i:0-v:a
i:1-v:b
i:2-v:c
i:3-v:d
i:4-v:...
答案2
得分: 3
你可以使用提供的长度和容量创建一个切片,内置的make()
函数接受一个可选的第三个参数作为容量:
l := make([]string, 0, 1000) // 使用足够的容量
这样,你可以在不需要`append()`重新分配(并隐式复制)内容的情况下追加元素,如果当前容量不足以执行追加操作。
还要注意,使用索引设置元素比追加更高效(使用`append()`时,即使大多数情况下返回的切片头部不变,你仍然需要将其赋值回去):
```go
c, l := 0, make([]string, 1000) // 使用足够的长度
l[c], c = "a", c+1
l[c], c = "b", c+1
l[c], c = "c", c+1
l[c], c = "d", c+1
l[c], c = "e", c+1
// 完成后,对切片进行切片操作:
l = l[:c]
for i, v := range l {
fmt.Printf("i:%d-v:%s\n", i, v)
}
输出结果(在Go Playground上尝试):
i:0-v:a
i:1-v:b
i:2-v:c
i:3-v:d
i:4-v:e
还要注意,在实际应用中,当你用来填充切片的值来自某个地方时,不需要手动处理计数器,循环会自动处理。例如:
c := 0
for ; c < 5; c++ {
l[c] = string('a' + c) // 获取下一个要存储在切片中的元素
}
// 完成后,对切片进行切片操作:
l = l[:c]
在Go Playground上尝试这个例子。
请注意,只有在你创建的切片足够大的情况下才能使用这种方法,否则当c
达到长度时,l[c]
会导致运行时恐慌。
英文:
You may create a slice using 0 length and capacity provided, the builtin make()
function takes an optional 3rd parameter being the capacity:
l := make([]string, 0, 1000) // Use a capacity that is enough for you
This way you can append elements without append()
having to reallocate (and implicitly copy) the contents if the current capacity is not enough to perform the append.
Also note that it is more efficient to set elements using indexing than appending (by using append()
you have to assign the returned slice header back even though most of the time it doesn't change):
c, l := 0, make([]string, 1000) // Use a length that is enough for you
l[c], c = "a", c+1
l[c], c = "b", c+1
l[c], c = "c", c+1
l[c], c = "d", c+1
l[c], c = "e", c+1
// We're done: slice the slice:
l = l[:c]
for i, v := range l {
fmt.Printf("i:%d-v:%s\n", i, v)
}
Output (try it on the Go Playground):
i:0-v:a
i:1-v:b
i:2-v:c
i:3-v:d
i:4-v:e
Also note that in practice when you fill your slice with values you receive from somewhere, the manual counter handling is not needed, a loop takes care of that. For example:
c := 0
for ; c < 5; c++ {
l[c] = string('a' + c) // Acquire next element to store in the slice
}
// We're done: slice the slice:
l = l[:c]
Try this one on the Go Playground.
Note that you can only use this though if you create a slice that you're sure won't be small, else l[c]
would give you a runtime panic when c
reaches the length.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论