golang 合并多个数组有优雅的写法吗?

在 Go 语言中,可以使用 append 函数来合并多个数组。例如,如果你有两个整数数组 ab,可以这样合并它们:

a := []int{1, 2, 3}
b := []int{4, 5, 6}
c := append(a, b...)

这样,c 就是一个新的数组,它包含了 ab 中的所有元素。注意,在调用 append 函数时,第二个参数后面要加上 ...,表示将第二个数组中的元素展开。

如果你有多个数组需要合并,可以重复调用 append 函数。例如:

a := []int{1, 2, 3}
b := []int{4, 5, 6}
c := []int{7, 8, 9}
d := append(a, b...)
d = append(d, c...)

这样,d 就是一个新的数组,它包含了 abc 中的所有元素。

new bing 给的写法,好丑陋, 如果多次 append嵌套 这个代码变得难看,不然就会多一些无用的临时变量
阅读 7.7k
3 个回答

专门写个方法,下面给出两个方式:

package main

import "fmt"

// For-loop 通过append一个空数组里面添加元素
func Merge(arrays ...[]int) []int {
    c := []int{}
    for _, a := range arrays {
        c = append(c, a...)
    }
    return c
}

// 预分配一个长度为所有数组大小的切片,然后通过copy的方式往里面拷贝替换
func ConcatCopyPreAllocate(slices [][]int) []int {
    var totalLen int
    for _, s := range slices {
        totalLen += len(s)
    }
    tmp := make([]int, totalLen)
    var i int
    for _, s := range slices {
        i += copy(tmp[i:], s)
    }
    return tmp
}

func main() {
    a := []int{1, 2, 3}
    b := []int{4, 5, 6}
    c := []int{7, 8, 9}
    d := Merge(a, b, c)

    fmt.Println(d)

    dd := ConcatCopyPreAllocate([][]int{a, b, c})

    fmt.Println(dd)
}

方式二的性能效果要好一些,仅供参考:

goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz
BenchmarkMerge-8                        10485656               107.7 ns/op           168 B/op          3 allocs/op
BenchmarkConcatCopyPreAllocate-8        21462087                51.60 ns/op           96 B/op          1 allocs/op
PASS
ok      command-line-arguments  2.737s

没什么优雅的写法,自己写个函数分配一次空间然后赋值就是了。有int版本和泛型版本。

// appendIntSlices 将多个 int 切片连接成一个新的 int 切片。
// 参数 slices 是要连接的 int 切片列表。
// 返回一个包含所有切片元素的新切片。
func appendIntSlices(slices ...[]int) []int {
    var totalLen int
    for _, s := range slices {
        totalLen += len(s)
    }
    result := make([]int, totalLen)
    begin := 0
    for _, s := range slices {
        begin += copy(result[begin:begin+len(s)], s)
    }
    return result
}

// appendSlices 将多个切片连接成一个新切片。
// 参数 slices 是要连接的切片列表,切片元素可以任意。
// 返回一个包含所有切片元素的新切片
func appendSlices[T any](slices ...[]T) []T {
    var totalLen int
    for _, s := range slices {
        totalLen += len(s)
    }
    result := make([]T, totalLen)
    begin := 0
    for _, s := range slices {
        begin += copy(result[begin:begin+len(s)], s)
    }
    return result
}

func main() {
    //用例
    s1 := []int{1, 2}
    s2 := []int{3, 4}
    s3 := []int{5, 6}
    fmt.Println(appendIntSlices(s1, s2, s3))
    fmt.Println(appendSlices(s1, s2, s3))
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题