为了账号安全,请及时绑定邮箱和手机立即绑定

Go 中的切片分块

Go 中的切片分块

Go
心有法竹 2021-12-07 18:31:05
我有一个包含大约 210 万个日志字符串的切片,我想创建一个切片,其中的字符串尽可能均匀分布。这是我到目前为止所拥有的:// logs is a slice with ~2.1 million strings in it.var divided = make([][]string, 0)NumCPU := runtime.NumCPU()ChunkSize := len(logs) / NumCPUfor i := 0; i < NumCPU; i++ {    temp := make([]string, 0)    idx := i * ChunkSize    end := i * ChunkSize + ChunkSize    for x := range logs[idx:end] {        temp = append(temp, logs[x])    }    if i == NumCPU {        for x := range logs[idx:] {            temp = append(temp, logs[x])        }    }    divided = append(divided, temp)}该idx := i * ChunkSize会给我目前的“块启动”为logs索引,end := i * ChunkSize + ChunkSize会给我“块结束”,或该块的范围的结束。我找不到任何关于如何在 Go 中分块/拆分切片或在有限范围内迭代的文档或示例,所以这就是我想出的。但是,它只会多次复制第一个块,因此它不起作用。我如何(尽可能均匀地)在 Go 中分块?
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

您不需要制作新切片,只需将切片附加logs到divided切片即可。


http://play.golang.org/p/vyihJZlDVy


var divided [][]string


chunkSize := (len(logs) + numCPU - 1) / numCPU


for i := 0; i < len(logs); i += chunkSize {

    end := i + chunkSize


    if end > len(logs) {

        end = len(logs)

    }


    divided = append(divided, logs[i:end])

}


fmt.Printf("%#v\n", divided)


查看完整回答
反对 回复 2021-12-07
?
BIG阳

TA贡献1859条经验 获得超6个赞

另一种变体。它的工作速度比JimB提出的快 2.5 倍。测试和基准测试在这里。


https://play.golang.org/p/WoXHqGjozMI


func chunks(xs []string, chunkSize int) [][]string {

    if len(xs) == 0 {

        return nil

    }

    divided := make([][]string, (len(xs)+chunkSize-1)/chunkSize)

    prev := 0

    i := 0

    till := len(xs) - chunkSize

    for prev < till {

        next := prev + chunkSize

        divided[i] = xs[prev:next]

        prev = next

        i++

    }

    divided[i] = xs[prev:]

    return divided

}


查看完整回答
反对 回复 2021-12-07
?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

对任何 []T 使用反射


https://github.com/kirito41dd/xslice


package main


import (

    "fmt"

    "github.com/kirito41dd/xslice"

)


func main() {

    s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

    i := xslice.SplitToChunks(s, 3)

    ss := i.([][]int)

    fmt.Println(ss) // [[0 1 2] [3 4 5] [6 7 8] [9]]

}

https://github.com/kirito41dd/xslice/blob/e50d91fa75241a3a03d262ad51c8e4cb2ea4b995/split.go#L12


func SplitToChunks(slice interface{}, chunkSize int) interface{} {

    sliceType := reflect.TypeOf(slice)

    sliceVal := reflect.ValueOf(slice)

    length := sliceVal.Len()

    if sliceType.Kind() != reflect.Slice {

        panic("parameter must be []T")

    }

    n := 0

    if length%chunkSize > 0 {

        n = 1

    }

    SST := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length/chunkSize+n)

    st, ed := 0, 0

    for st < length {

        ed = st + chunkSize

        if ed > length {

            ed = length

        }

        SST = reflect.Append(SST, sliceVal.Slice(st, ed))

        st = ed

    }

    return SST.Interface()

}


查看完整回答
反对 回复 2021-12-07
  • 3 回答
  • 0 关注
  • 193 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信