明月笑刀无情
你可以在golang/SliceTricks找到一些有用的技巧。自从引入append内置函数以来container/vector,在 Go 1 中删除的包的大部分功能都可以使用append和复制copy。以下是向量方法及其切片操作类似物:追加向量a = append(a, b...)复制b = make([]T, len(a))copy(b, a)// orb = append([]T(nil), a...)切a = append(a[:i], a[j:]...)删除a = append(a[:i], a[i+1:]...)// ora = 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 Ta = a[:len(a)-1]删除而不保留顺序a[i] = a[len(a)-1]a[len(a)-1] = nila = 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创建一个具有自己底层存储的新切片a[i:],并将元素复制到该切片中,然后将这些元素复制回切片a(由第一个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) }}倒车用相同的元素但以相反的顺序替换切片的内容:for i := len(a)/2-1; i >= 0; i-- { opp := len(a)-1-i a[i], a[opp] = a[opp], a[i]}同样的事情,除了两个索引:for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 { a[left], a[right] = a[right], a[left]}洗牌费雪-耶茨算法:for i := len(a) - 1; i > 0; i-- { j := rand.Intn(i + 1) a[i], a[j] = a[j], a[i]}