首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么追加修改传递的片

为什么追加修改传递的片
EN

Stack Overflow用户
提问于 2016-03-10 15:22:26
回答 5查看 10.4K关注 0票数 19

除了当前元素之外,我如何遍历该切片并将其传递到某个位置?似乎正如我们在文档中看到的那样,追加()函数修改了底层的切片。但不管怎样,我还是不知道怎么达到这个目标。

代码语言:javascript
复制
func main() {
    args := []string{ "2", "3", "8" }

    for i, _ := range args {
        fmt.Println(append(args[:i], args[i+1:]...)) // or pass to function
    }

    fmt.Println(args)
}

结果:

代码语言:javascript
复制
[3 8]
[3 8]
[3 8]
[3 8 8] // it is args now

我所期望的:

代码语言:javascript
复制
 [3 8]
 [2 8]
 [2 3]

我已经看过这个为什么append()要修改提供的片?(见示例)

但是,对我来说,切片的容量是什么,我不明白为什么我会超过它。

EN

回答 5

Stack Overflow用户

发布于 2016-03-10 16:04:21

表现是最重要的原因。创建一个新的切片并将所有元素复制到其中是很昂贵的,因此切片代码不会在没有充分理由的情况下进行复制。但是,如果您超过了该片的容量,则通过复制基础片,它会以适当的数量增长。这意味着从append返回的片可能不是您传入的同一片。

最好的使用方式是:

代码语言:javascript
复制
args = append(args, newarg)

如果使用子片,容量将保持不变,但切片中的视图会发生变化。这意味着缺失的元素仍然存在,但超出了新切片的范围。

这解释了代码的奇怪输出。每次都要打印append的结果,但不存储结果,这意味着args与您打印的结果不一样。

初始的args切片是3个元素大。对于每个索引i --也就是说,对于012 --您需要一个子切片args[:i],并将数组args[i+1:]的其余部分的所有元素附加到它。这意味着:

代码语言:javascript
复制
i    args[:i]     args[i+1:]...   Result         args
0    {}           {"3", "8"}     {"3", "8"}     {"3", "8", "8"}
1    {"3"}        {"8"}          {"3", "8"}     {"3", "8", "8"}
2    {"3", "8"}   {}             {"3", "8"}     {"3", "8", "8"}

tl;博士,您应该始终保存append的结果,如果您想复制一个副本以便您可以更改它,那么自己制作一个副本。

票数 12
EN

Stack Overflow用户

发布于 2016-03-10 15:46:29

追加总是尝试修改基础数组。

让我们看一下循环的第一次执行。

代码语言:javascript
复制
append(args[:0], args[0+1:]...)

这样做是将片{3,8}追加到片{},因为args:0给出了一个在数组开始时结束的空片。这就是为什么您的数组显示为3 8 8,因为3 8被附加到数组中。阅读有关此在维基上的更多信息。

可以使用make设置默认容量,即

代码语言:javascript
复制
args := make([]string, 0, CAPACITY)

您还可以检查片的容量。

代码语言:javascript
复制
a := []int{1,2,3}
fmt.Println(cap(a))
>>> 3

最后,如果您不想每次都像Elwinar的回答那样重新记录数组,我建议将两个片段a:i和ai+1:传递给函数。

票数 6
EN

Stack Overflow用户

发布于 2016-03-10 17:05:33

Go程序设计语言规范 附加和复制切片 内置函数在普通切片操作中附加和复制辅助功能。对于这两个函数,结果与参数引用的内存是否重叠无关。 变量函数附加零或多个S类型的值x到S,这必须是片类型,并返回结果片,也是S类型。值x传递给...T类型的参数,其中T是S的元素类型,相应的参数传递规则适用。作为特例,追加还接受可指定键入[]字节的第一个参数,第二个字符串类型的参数后面跟着.此表单附加字符串的字节。 附加(s S,x ...T) S // T是S的元素类型 如果s的容量不足以满足附加值,则追加一个新的、足够大的基础数组,该数组既适合现有的片元素,也适合附加的值。否则,追加重新使用基础数组。 s0 := []int{0,0} s1 := append(s0,2) //追加单个元素s1 == []int{0,0,2} s2 :=追加(s1,3,5,7) //附加多个元素s2 == []int{0,0,2,3,5,7} s3 :=附加(s2,s0.) //追加片s3 s0 []int{0,0,2,3,5,7,0,0} s4 :=追加(S33:6,s32:.) //追加重叠切片s4 == []int{3,5,7,2,3,5,7,0,0} var t[]接口{}t= append(t,42,3.1415,"foo") // t == []接口{42,3.1415,"foo"} var b[]b= append(b,//追加字符串内容b == []字节{‘b’,'a','r‘} 函数复制将片元素从源src复制到目标dst,并返回复制的元素数。这两个参数必须具有相同的元素类型T,并且必须分配给类型[]T的一个片段。复制的元素数是len(src)和len(dst)的最小值。作为特例,copy还接受一个指定为使用字符串类型的源参数键入[]字节的目标参数。此表单将字节从字符串复制到字节片中。 复制(dst,src []T) int复制(dst[]字节,src字符串) int 示例: var a= ...int{0,1,2,3,4,5,6,7} var s= make([]int,6) var b=make([]字节,5) n1 := copy(s,a0:) / n1 == 6,s == []int{0,1,2,3,4,5} n2 := copy(s,s2:) // n2 == 4,s == []int{2,3,4,5,4,4,5} n3 :=复制(b,"Hello,World!") // n3 == 5,b == []字节(“Hello”)

不要使用附件覆盖您的输入。为输出使用单独的变量(函数参数)。例如,

代码语言:javascript
复制
package main

import "fmt"

func main() {
    args := []string{"2", "3", "8"}
    fmt.Println(args)
    funcArg := make([]string, len(args)-1)
    for i := range args {
        copy(funcArg, args[:i])
        copy(funcArg[i:], args[i+1:])
        fmt.Println(funcArg)
    }
    fmt.Println(args)
}

输出:

代码语言:javascript
复制
[2 3 8]
[3 8]
[2 8]
[2 3]
[2 3 8]
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35920534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档