美文网首页
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 操作常用技巧

    复制 使用内置的 copy 函数 插入元素 开头插入 需要注意的是,在切片开头插入元素,一般都会导致内存的重新分配...

  • JavaScript获取数组的片段

    JavaScript中数组的常用操作之获取数组的片段 Array.slice() 方法 Array.slice([...

  • go之slice

    slice中文切片的意思,是go独有的类型,底层是数组,可以很方便的进行截取,也支持扩容、拷贝操作 slice 创...

  • Go语言——Slice分析

    Go语言——Slice分析 源码很不好找,在go\src\runtime\slice.go。 根据容量cap*元素...

  • go 中的slice 合并

    go 中的切片合并即两个 slice 相加使用 go 语言内置的append 方法,我们比较常用的是 添加单个元素...

  • Go中的Array和Slice

    Go中的Array和Slice 翻译来于:https://blog.golang.org/slices 操作 ex...

  • Go slice那些事

    今晚闲来无事,总结一下Go的slice slice是什么slice在Go中的原型?slice类似数组,是一种定长的...

  • Go操作MySQL

    Go语言操作MySQL MySQL是业界常用的关系型数据库,本文介绍了Go语言如何操作MySQL数据库。 Go操作...

  • 深入理解 Go Slice

    原文地址:深入理解 Go Slice 是什么 在 Go 中,Slice(切片)是抽象在 Array(数组)之上的特...

  • Go操作MySQL

    MySQL是业界常用的关系型数据库,本文介绍了Go语言如何操作MySQL数据库。 Go操作MySQL 连接 Go语...

网友评论

      本文标题:go slice 操作常用技巧

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