在GO语言

时间:2015-11-20 19:37:14

标签: arrays go append slice

我有2个数组声明为: var input []stringvar output []string

输入数组最初填充了一些ID。输出数组为NULL。

每次迭代后,我想从输入数组中删除一个随机元素并将其添加到输出数组中。

最后,输出数组中的所有元素将与输入数组相同(但具有不同的排序(索引))。

for index := 0; index < len(input); index++ {
    if !visited[index] {
        //do something
    }
}
output[#iteration index] = input[current index]

当我尝试这样做时,我得到array out of bounds error

2 个答案:

答案 0 :(得分:19)

对于output数组,您需要使用append或使用初始容量分配它以匹配input的大小。

// before the loop
output := make([]string, len(input))

将是我的建议,因为append会导致大量不必要的重新分配,并且您已经知道您需要什么容量,因为它基于input

另一件事是:

output = append(output, input[index])

但就像我说的那样,从我观察到的附加物中,初始容量呈指数增长。如果您没有指定任何意味着您在达到所需容量之前将要进行多次不需要的重新分配,那么这将是基数2。

答案 1 :(得分:2)

你可以在golang/SliceTricks找到一些有用的技巧。

自引入append内置版以来,在{1}中删除的container/vector包的大部分功能都可以使用append和{{1}进行复制}}

以下是矢量方法及其切片操作类似物:

AppendVector
copy
复制
a = append(a, b...)
b = make([]T, len(a))
copy(b, a)
// or
b = append([]T(nil), a...)
删除
a = append(a[:i], a[j:]...)
删除而不保留​​订单
a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]

注意如果元素的类型是指针或带有指针字段的结构,需要进行垃圾回收,则a[i] = a[len(a)-1] a = a[:len(a)-1] 的上述实现并且Cut有潜在的内存泄漏问题:某些带有值的元素仍然被片Delete引用,因此无法收集。以下代码可以解决此问题:

  

<强>剪切

a
  

删除

copy(a[i:], a[j:])
for k, n := len(a)-j+i, len(a); k < n; k++ {
    a[k] = nil // or the zero value of T
}
a = a[:len(a)-j+i]
  

删除而不保留​​订单

copy(a[i:], a[i+1:])
a[len(a)-1] = nil // or the zero value of T
a = a[:len(a)-1]
扩大
a[i] = a[len(a)-1]
a[len(a)-1] = nil
a = a[:len(a)-1]
延伸
a = append(a[:i], append(make([]T, j), a[i:]...)...)
插入
a = append(a, make([]T, j)...)

注意第二个a = append(a[:i], append([]T{x}, a[i:]...)...) 创建一个带有自己的底层存储的新切片,并将append中的元素复制到该切片,然后将这些元素复制回切片{ {1}}(由第一个a[i:])。通过使用替代方法可以避免创建新切片(以及因此内存垃圾)和第二个副本:

  

插入

a
InsertVector
append
流行的
s = append(s, 0)
copy(s[i+1:], s[i:])
s[i] = x
回弹
a = append(a[:i], append(b, a[i:]...)...)
x, a = a[0], a[1:]
推前
x, a = a[len(a)-1], a[:len(a)-1]
转移
a = append(a, x)
不印字
a = append([]T{ x }, a...)

其他技巧

过滤而不分配

此技巧使用切片与原始切片共享相同的后备阵列和容量这一事实,因此存储将重用于过滤切片。当然,原始内容会被修改。

x, a := a[0], a[1:]

倒车

使用相同的元素替换切片的内容,但顺序相反:

a = append([]T{x}, a...)

同样的事情,除了两个指数:

b := a[:0]
for _, x := range a {
    if f(x) {
        b = append(b, x)
    }
}

洗牌

Fisher-Yates算法:

for i := len(a)/2-1; i >= 0; i-- {
    opp := len(a)-1-i
    a[i], a[opp] = a[opp], a[i]
}