美文网首页
go slice 操作常用技巧

go slice 操作常用技巧

作者: wayyyy | 来源:发表于2022-08-27 01:39 被阅读0次
    复制

    使用内置的 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 操作常用技巧

          本文链接:https://www.haomeiwen.com/subject/uwnxnrtx.html