英文:
variadic pack and unpack in go lang: '[]string{f(v)}...'
问题
我在浏览 GitHub 时找到了这个函数:
func Accumulate(s []string, f func(st string) string) (result []string) {
    for _, v := range s {
        result = append(result, []string{f(v)}...)
    }
    return result
}
这个方法可以简化为以下形式吗?还是我漏掉了什么?
func Accumulate(s []string, f func(st string) string) (result []string) {
    for _, v := range s {
        result = append(result, f(v))
    }
    return result
}
英文:
I found this function while browsing github:
func Accumulate(s []string, f func(st string) string) (result []string) {
    for _, v := range s {
        result = append(result, []string{f(v)}...)
    }
    return result
}
Could this method be simplified to the following, or am I missing something:
func Accumulate(s []string, f func(st string) string) (result []string) {
    for _, v := range s {
        result = append(result, f(v))
    }
    return result
}
答案1
得分: 1
你提供的代码是正确的,易于理解的。我写了一个基准测试:
package p
import (
    "testing"
    "strings"
)
var s = []string{"hello", "world", "this", "new", "world"}
func BenchmarkAcc1(b *testing.B) {
    for n := 0; n < b.N; n++ {
        Accumulate(s, strings.ToUpper)
    }
}
func BenchmarkAcc2(b *testing.B) {
    for n := 0; n < b.N; n++ {
        Accumulate2(s, strings.ToUpper)
    }
}
以下是我得到的一些结果:
% go test -benchtime=10s -bench=.
testing: warning: no tests to run
PASS
BenchmarkAcc1    10000000    1510 ns/op
BenchmarkAcc2    10000000    1492 ns/op
ok    _/home/satran/test    33.064s
如你所见,实际上并没有性能提升,事实上你的版本效果更好。
以下是源代码:
package p
func Accumulate(s []string, f func(st string) string) (result []string) {
    for _, v := range s {
        result = append(result, []string{f(v)}...)
    }
    return result
}
func Accumulate2(s []string, f func(st string) string) (result []string) {
    for _, v := range s {
        result = append(result, f(v))
    }
    return result
}
希望对你有帮助!
英文:
The version you have written is correct and sane to understand. I wrote a benchmark:
package p
import (
    "testing"
    "strings"
)
var s = []string{"hello", "world", "this", "new", "world"}
func BenchmarkAcc1(b *testing.B) {
	for n := 0; n < b.N; n++ {
		Accumulate(s, strings.ToUpper)
	}
}
func BenchmarkAcc2(b *testing.B) {
	for n := 0; n < b.N; n++ {
		Accumulate2(s, strings.ToUpper)
	}
}
Here are a few results I got:
% go test -benchtime=10s -bench=.
testing: warning: no tests to run
PASS
BenchmarkAcc1	10000000	      1510 ns/op
BenchmarkAcc2	10000000	      1492 ns/op
ok  	_/home/satran/test	33.064s
As you can see there is no performance gain either, in fact your version works better.
Here is the source:
package p
func Accumulate(s []string, f func(st string) string) (result []string) {
	for _, v := range s {
		result = append(result, []string{f(v)}...)
	}
	return result
}
func Accumulate2(s []string, f func(st string) string) (result []string) {
	for _, v := range s {
		result = append(result, f(v))
	}
	return result
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论