Golang slice高级应用

原文参考:https://github.com/golang/go/wiki/SliceTricks
代码示例:

package main
import "fmt"
func initSliceValue(s []int) {
    for i := 0; i < len(s); i++ {
        s[i] = i
    }
}
func main() {
    // Append vector
    v1 := make([]int, 3)
    initSliceValue(v1)
    v2 := make([]int, 3)
    initSliceValue(v2)
    v1 = append(v1, v2...)
    fmt.Printf("v1=%v\n", v1)
    fmt.Printf("v2=%v\n", v2)
    // Copy slice value
    a := make([]int, 3)
    initSliceValue(a)
    b := make([]int, len(a))
    copy(b, a)
    fmt.Printf("b=%v\n", b)
    b1 := append([]int(nil), a...) // 打散方式只是复制,不是原来的值
    a[0] = 10
    fmt.Printf("b1=%v\n", b1)
    // Cut slice
    c := make([]int, 10)
    initSliceValue(c)
    c = append(c[:3], c[5:]...)
    fmt.Printf("c=%v, len(c)=%v, cap(c)=%v\n", c, len(c), cap(c))
    // Delete index i
    d := make([]int, 10)
    initSliceValue(d)
    i := 5
    d = append(d[:i], d[i+1:]...) // 打散追加,O(N)
    fmt.Printf("d=%v\n", d)
    d1 := make([]int, 10)
    d1 = d1[:i+copy(d1[i:], d1[:i+1])] // copy追加,O(N)
    fmt.Printf("d1=%v\n", d1)
    // Delete without preserving order
    e := make([]int, 10)
    initSliceValue(e)
    e[i] = e[len(e)-1] // O(1)
    e = e[:len(e)-1]
    // If the type of the element is a pointer or a struct with pointer fields,
    // which need to be garbage collected, the above implementations of Cut and
    // Delete have a potential memory leak problem: some elements with values are
    // still referenced by slice a and thus can not be collected. The following code can fix this problem:
    // Cut
    i = 3
    j := 5
    f := make([]*int, 10)
    copy(f[i:], f[j:])
    for k, n := len(f)-j+i, len(f); k < n; k++ {
        f[k] = nil
    }
    // Delete
    g := make([]*int, 10)
    if i < len(g) {
        copy(g[:i], g[i+1:])
        g[i] = nil
    }
    // Delete without preserving order
    h := make([]*int, 10)
    h[i] = h[len(h)-1]
    h[len(h)-1] = nil
    h = h[:len(h)-1]
    // Expand elements before x[i]
    i = 5
    n := 5
    x := make([]int, 10)
    initSliceValue(x)
    x = append(x[:i], append(make([]int, n), x[i:]...)...)
    fmt.Printf("x=%v\n", x)
    // Extend
    y := make([]int, 5)
    initSliceValue(y)
    y = append(y, make([]int, 5)...)
    fmt.Printf("y=%v\n", y)
}

输出结果:

v1=[0 1 2 0 1 2]
v2=[0 1 2]
b=[0 1 2]
b1=[0 1 2]
c=[0 1 2 5 6 7 8 9], len(c)=8, cap(c)=10
d=[0 1 2 3 4 6 7 8 9]
d1=[0 0 0 0 0 0 0 0 0 0]
x=[0 1 2 3 4 0 0 0 0 0 5 6 7 8 9]
y=[0 1 2 3 4 0 0 0 0 0]

第二部分:

package main
import (
    "fmt"
    "math/rand"
    "sort"
)
func initSliceValue(s []int) {
    for i := 0; i < len(s); i++ {
        s[i] = i
    }
}
func isEvenNumber(a int) bool {
    return a%2 == 0
}
func main() {
    // filter
    n := 0
    a := make([]int, 10)
    initSliceValue(a)
    for _, x := range a {
        if isEvenNumber(x) {
            a[n] = x
            n++
        }
    }
    a = a[:n]
    fmt.Printf("a=%v\n", a)
    // insert element
    b := make([]int, 5)
    initSliceValue(b)
    i := 3
    b = append(b[:i], append([]int{-1}, b[i:]...)...)
    fmt.Printf("b=%v\n", b)
    // push & pop
    c := make([]int, 5)
    c = append(c, -1)
    fmt.Printf("c=%v\n", c)
    var x int
    x, c = c[len(c)-1], c[:len(c)-1]
    fmt.Printf("x=%v, c=%v\n", x, c)
    // filter without allocation
    d := make([]int, 10)
    initSliceValue(d)
    e := d[:0]
    for _, x := range d {
        if isEvenNumber(x) {
            e = append(e, x)
        }
    }
    fmt.Printf("d=%v, e=%v\n", d, e)
    // alternative choice, if d store pointer
    // for i := len(e); i < len(d); i++ {
    //  d[i] = nil
    // }
    // reverse slice
    f := make([]int, 10)
    initSliceValue(f)
    for i := len(f)/2 - 1; i >= 0; i-- {
        opp := len(a) - 1 - i
        a[i], a[opp] = a[opp], a[i]
    }
    fmt.Printf("f=%v\n", f)
    // batching with minimal allocation
    actions := make([]int, 10)
    initSliceValue(actions)
    batchSize := 3
    var batches [][]int
    for batchSize < len(actions) {
        actions, batches = actions[batchSize:], append(batches, actions[0:batchSize:batchSize])
    }
    batches = append(batches, actions) // append rest elements
    fmt.Printf("batches=%v\n", batches)
    
    // In-place deduplicate
    in := make([]int, 9)
    for i := 0; i < len(in); i++ {
        in[i] = rand.Intn(len(in) / 2)
    }
    sort.Ints(in)
    fmt.Println(in)
    j := 0
    for i := 1; i < len(in); i++ {
        if in[i] == in[j] {
            continue
        }
        j++
        in[j] = in[i]
    }
    result := in[:j+1]
    fmt.Printf("result=%v\n", result)
}

输出结果:

a=[0 2 4 6 8]
b=[0 1 2 -1 3 4]
c=[0 0 0 0 0 -1]
x=-1, c=[0 0 0 0 0]
d=[0 2 4 6 8 5 6 7 8 9], e=[0 2 4 6 8]
f=[0 1 2 3 4 5 6 7 8 9]
batches=[[0 1 2] [3 4 5] [6 7 8] [9]]
[0 0 1 1 1 2 3 3 3]
result=[0 1 2 3]

你可能感兴趣的:(Go语言笔记)