Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 删除切片中的每个元素_Go - Fatal编程技术网

Go 删除切片中的每个元素

Go 删除切片中的每个元素,go,Go,当我尝试循环通过一个切片并按顺序删除每个元素以打印其余元素时,我遇到了一些意想不到的行为,使用建议的Delete方法。例如,当我尝试循环一个包含字母[ab C]的切片时,我希望输出是[bc],[ac],[ab],顺序如下: 方法1 package main import "fmt" func main() { a := []string {"A", "B", "C"} for i, _ := range a { fmt.Println(append(a[:i]

当我尝试循环通过一个切片并按顺序删除每个元素以打印其余元素时,我遇到了一些意想不到的行为,使用建议的Delete方法。例如,当我尝试循环一个包含字母
[ab C]
的切片时,我希望输出是
[bc]
[ac]
[ab]
,顺序如下:

方法1

package main

import "fmt"

func main() {
    a := []string {"A", "B", "C"}
    for i, _ := range a {
        fmt.Println(append(a[:i], a[i+1:]...))
    }
}
然而,这里的输出令我惊讶。它输出三次
[bc]

通过以下操作,我最终获得了预期的行为:

方法2

package main

import "fmt"

func main() {
    a := []string {"A", "B", "C"}
    for i, _ := range a {
        result := make([]string, 0)
        result = append(result, a[:i]...)
        result = append(result, a[i+1:]...)
        fmt.Println(result)
    }
}

方法1中出现意外行为的原因是什么?除了方法2之外,还有其他更好的方法吗?

查看第一次迭代后发生的情况:

package main

import "fmt"

func main() {
    a := []string{"A", "B", "C"}
    x := append(a[:0], a[1:]...)
    fmt.Println(a)
    fmt.Println(x)
}
给予

[B C C]
[B C]

接下来的两个迭代是相似的。试一试。

因为“what”实际上是在用新元素更新
片段。它返回一个“新”片只是因为它可能由于内存重新分配而不得不重新定位原始片。因此,在示例代码中,您实际上是在每次调用
append
时更改
a
的内容。(golang博客文章的“附加:示例”部分提供了一个很好的概述)

至于“如何”,我的尝试是:

package main

import "fmt"

func main() {
    a := []string {"A", "B", "C"}
    for i, _ := range a {
        result := make([]string, i, len(a)-1)
        copy(result, a[:i])
        result = append(result, a[i+1:]...)
        fmt.Println(result)
    }
}


使用长度和容量初始化
result
,以及使用
copy
而不是两次
append
s尝试减少所需的内存重新分配次数。

如果不想进行额外分配,请尝试只交换值,如图所示:

请注意,这假设您可以洗牌列表内容。 如果没有,只需在循环之前复制列表一次,并执行以下操作

package main

import "fmt"

func main() {
    set := []string{"a", "b", "c"}
    for i := range set {
        set[0], set[i] = set[i], set[0]
        fmt.Println(set[1:])
    }
}
输出:

[b c]
[a c]
[a b]

无法从append分配值通常是一个错误mistake@JimB这是OP的一个要求。基本上就是打印一个切片,每次按顺序删除一个元素。OP:这样的切片索引和速记是不可能的。您必须更详细一点。您可以跳过迭代0中的交换,因为将x[0]与x[0]交换是不可操作的。这对发生意外行为的原因给出了最佳解释,也给出了可接受的替代方案。不过,我更喜欢@jimt提供的解决方案。