Go 中的切片分块

新手上路,请多包涵

我有一个包含约 210 万个日志字符串的切片,我想创建一个切片,其中的字符串尽可能均匀分布。

这是我到目前为止所拥有的:

 // logs is a slice with ~2.1 million strings in it.
var divided = make([][]string, 0)
NumCPU := runtime.NumCPU()
ChunkSize := len(logs) / NumCPU
for 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 中分块切片?

原文由 SiennaD. 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 871
2 个回答

您不需要制作新的切片,只需将 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)

原文由 JimB 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用泛型(Go 版本 >=1.18):

 func chunkBy[T any](items []T, chunkSize int) (chunks [][]T) {
    for chunkSize < len(items) {
        items, chunks = items[chunkSize:], append(chunks, items[0:chunkSize:chunkSize])
    }
    return append(chunks, items)
}

游乐场网址

或者,如果您想手动设置容量:

 func chunkBy[T any](items []T, chunkSize int) [][]T {
    var _chunks = make([][]T, 0, (len(items)/chunkSize)+1)
    for chunkSize < len(items) {
        items, _chunks = items[chunkSize:], append(_chunks, items[0:chunkSize:chunkSize])
    }
    return append(_chunks, items)
}

游乐场网址

原文由 Alfonso 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题