go slice 操作常用技巧

复制

使用内置的 copy 函数

b = make([]T, len(a))  // 一次将内存申请到位
copy(b, a)
插入元素

开头插入

var a = []int{1, 2, 3}
a = append([]int{0}, a...)  // 在开头添加一个元素

需要注意的是,在切片开头插入元素,一般都会导致内存的重新分配和已有元素的全部复制一次。

中间插入

var a = []int{1, 2, 3}
    
a = append(a, 0)    // 扩充空间
copy(a[i+1:], a[i])  // a[i:] 向后移动一个元素
a[i] = 10  // 设置新的元素
删除元素

开头或者结尾删除:

var a = []int{1, 2, 3}
a = a[1:]  // 开头删除
a = a[:len(a)-1]  // 结尾删除  

中间删除:

var a = []int{1, 2, 3, 4, 5, 6}
a = a[:2 + copy(a[2:], a[2+1:])]    // 删除第2个元素, 公式:  a[: i + copy(a[i:], a[i+1:])]
fmt.Println("a: ", a)  // a:  [1 2 4 5 6]

var b = []int{1, 2, 3, 4, 5, 6}
b = b[:1 + copy(b[1:], b[1+3:])]    // 删除[1, 1+3)元素, 公式:  b[: i + copy(b[i:], b[i+N:])]
fmt.Println("b: ", b)  // a:  [1 2 4 5 6]
过滤
n := 0
for _, x := range a {
   if keep(x) {
       a[n] = x  // 保留该元素
       n++
   }
}
a = a[:n]  // 截取切片中需保留的元素
弹出元素

将切片a的最后一个元素弹出。

x, a = a[len(a)-1], a[:len(a)-1]

弹出切片a的第一个元素。

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

双指针

for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
   a[left], a[right] = a[right], a[left]
}
打乱顺序

Fisher–Yates算法:

for i := len(a) - 1; i > 0; i-- {
    j := rand.Intn(i + 1)
    a[i], a[j] = a[j], a[i]
}

从go1.10开始,可以使用math/rand.Shuffle。

rand.Shuffle(len(a), func(i, j int) {
    a[i], a[j] = a[j], a[i]
})
分批处理
actions := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
batchSize := 5
batches := make([][]int, 0, (len(actions) + batchSize - 1) / batchSize)

for batchSize < len(actions) {
    actions, batches = actions[batchSize:], append(batches, actions[0:batchSize:batchSize])
}
batches = append(batches, actions)

fmt.Println(batches)  // 输出:[[0 1 2 3 4] [5 6 7 8 9]]
就地删除重复元素
滑动窗口
func main() {
    a := []int{1, 2, 3, 4, 5}
    res := slidingWindow(2, a)
    fmt.Println(res)  // 输出:[[1 2] [2 3] [3 4] [4 5]]
}

func slidingWindow(size int, input []int) [][]int {
    // 返回入参的切片作为第一个元素
    if len(input) <= size {
        return [][]int{input}
    }

    // 以所需的精确大小分配切片
    r := make([][]int, 0, len(input)-size+1)

    for i, j := 0, size; j <= len(input); i, j = i+1, j+1 {
        r = append(r, input[i:j])
    }

    return r
}

参考资料
1、https://mp.weixin.qq.com/s/362m-GsKqLmrh5kbHp4Maw

你可能感兴趣的:(go slice 操作常用技巧)