帮助函数来分块任何切片?

huangapple go评论81阅读模式
英文:

Helper function to chunk any slice?

问题

我创建了一个小的辅助函数,用于将一个包含大量项目的数组拆分为最大大小为n的小数组。

func toPackages(e []int, n int) [][]int {
    var p [][]int
    packets := int(math.Ceil(float64(len(e)) / float64(n)))
    for i := 0; i < packets; i++ {
        start := i * n
        end := n * (i + 1)
        if len(e) < end {
            end = len(e)
        }
        p = append(p, e[start:end])
    }
    return p
}

Golang Playground上有一个工作示例。在程序中,我有几种不同类型的数组需要拆分。我尝试将其转换为使用interface{}接口。

英文:

I created a small helper function to split a large array of items into smaller arrays with a maximum size of n.

func toPackages(e []int, n int) [][]int {
    var p [][]int
    packets := int(math.Ceil(float64(len(e)) / float64(n)))
    for i := 0; i &lt; packets; i++ {
        start := i * n
        end := n * (i + 1)
        if len(e) &lt; end {
            end = len(e)
        }
        p = append(p, e[start:end])
    }
    return p
}

Working example at Golang Playground.
In the program I have several different types of arrays I would like to split. I have tried converting it to using interfaces with interface{}.

答案1

得分: 3

很难编写一个通用函数来很好地处理这个问题。你经常会花费很多代码将[]int转换为[]interface{},然后再转换回来,而这与仅仅复制代码片段所需的代码量相当。不过,我有一种稍微更好的方法:

playground链接

func splitInts(src []int, n int) (p [][]int){
    for len(src) > n{
        p = append(p,src[:n])
        src = src[n:]
    }
    if(len(src) > 0){
        p = append(p,src)
    }
    return p
}

函数中的任何内容都不会因为类型而改变,可以轻松地复制到:

func splitStrings(src []string, n int) (p [][]string){
    for len(src) > n{
        p = append(p,src[:n])
        src = src[n:]
    }
    if(len(src) > 0){
        p = append(p,src)
    }
    return p
}

只需更改第一行即可。

英文:

It is pretty hard to make a generic function to handle this well. You will often spend as much code converting []int to []interface{} and back, as it is to just copy the snippet. I do have a slightly nicer way to do it though:

playground link

func splitInts(src []int, n int) (p [][]int){
    for len(src) &gt; n{
	    p = append(p,src[:n])
	    src = src[n:]
	}
	if(len(src) &gt; 0){
	    p = append(p,src)
	}
	return p
}

Nothing in the function changes because of types, it can easily be copied to:

func splitStrings(src []string, n int) (p [][]string){
    for len(src) &gt; n{
	    p = append(p,src[:n])
	    src = src[n:]
	}
	if(len(src) &gt; 0){
	    p = append(p,src)
	}
	return p
}

By only changing the first line.

答案2

得分: 0

通常,对于每种类型,直接编写所需的函数是一个好主意。这也涉及到速度的问题:如果使用反射来编写通用函数,它的速度不会很快。

如果你仍然想要一个通用函数,可以使用以下代码:

func genToPackages(e interface{}, n int) interface{} {
    t := reflect.TypeOf(e)
    if t.Kind() != reflect.Slice {
        log.Println("e必须是一个切片")
    }
    v := reflect.ValueOf(e)

    packets := int(math.Ceil(float64(v.Len()) / float64(n)))
    p := reflect.MakeSlice(reflect.SliceOf(t), packets, packets)
    for i := 0; i < packets; i++ {
        s := reflect.MakeSlice(t, n, n)
        start := i * n
        for j := 0; j < n; j++ {
            s.Index(j).Set(v.Index(j+start))
        }

        p.Index(i).Set(s)
    }

    return p.Interface()
}

你需要将结果转换为你期望的类型。例如:

res := genToPackages([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 5).([][]int)

请注意,这只是一个示例,你需要根据你的实际需求进行适当的修改。

英文:

Generally it is a good idea to just write the function for every type you need it for. This is also a matter of speed: if you use reflect to write a generic function it will not be as fast.

If you still want a generic function here it is:

func genToPackages(e interface{}, n int) interface{} {
	t := reflect.TypeOf(e)
	if t.Kind() != reflect.Slice {
		log.Println(&quot;e has to be a slice&quot;)
	}
	v := reflect.ValueOf(e)

	packets := int(math.Ceil(float64(v.Len()) / float64(n)))
	p := reflect.MakeSlice(reflect.SliceOf(t), packets, packets)
	for i := 0; i &lt; packets; i++ {
		s := reflect.MakeSlice(t, n, n)
		start := i * n
		for j := 0; j &lt; n; j++ {
			s.Index(j).Set(v.Index(j+start))
		}

		p.Index(i).Set(s)
	}

	return p.Interface()
}

You will have to cast the result to the type you expect. For example:

res := genToPackages([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 5).([][]int)

huangapple
  • 本文由 发表于 2017年8月1日 23:14:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/45441611.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定