创建一个新的切片,给定一个先前的切片,但不包含给定的值。

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

Create a new slice given a previous one, without a given value

问题

我有一个字符串切片。我需要做的是在不知道索引的情况下从切片中删除一个值。我认为这是最简单的方法:

  1. // 返回一个不包含指定字符串的切片
  2. func newSliceWithout(s []string, without string) []string {
  3. l := []string{}
  4. for _, elem := range s {
  5. if elem != without {
  6. l = append(l, elem)
  7. }
  8. }
  9. return l
  10. }

然而,当进行基准测试时,我得到了相当高的值(如预期),所以我想知道是否有更快/更高效的方法来做到这一点?

英文:

I have a slice of strings. What I need to accomplish is to remove one value from the slice, without knowing the index. I thought this would be the easiest way to do it:

  1. // Return a slice that is the original without the given string
  2. func newSliceWithout(s []string, without string) []string {
  3. l := []string{}
  4. for _, elem := range s {
  5. if elem != without {
  6. l = append(l, elem)
  7. }
  8. }
  9. return l
  10. }

However, when performing benchmarks I get pretty high values (as expected), so I'm wondering if there's a faster / more efficient way to do it?

答案1

得分: 3

在一步中分配一个大的返回切片(由输入切片估计大小),不使用append(),而是分配给单个元素:

  1. func newSliceWithout(s []string, without string) []string {
  2. l, i := make([]string, len(s)), 0
  3. for _, elem := range s {
  4. if elem != without {
  5. l[i] = elem
  6. i++
  7. }
  8. }
  9. return l[:i]
  10. }

测试代码:

  1. x := newSliceWithout([]string{"a", "b", "a", "c"}, "a")
  2. fmt.Println(x)

输出结果(在Go Playground上尝试):

  1. [b c]

基准测试

  1. func BenchmarkNewSliceWithoutOrig(b *testing.B) {
  2. for n := 0; n < b.N; n++ {
  3. newSliceWithoutOrig([]string{"a", "b", "a", "c"}, "a")
  4. }
  5. }
  6. func BenchmarkNewSliceWithout(b *testing.B) {
  7. for n := 0; n < b.N; n++ {
  8. newSliceWithout([]string{"a", "b", "a", "c"}, "a")
  9. }
  10. }

结果:

  1. BenchmarkNewSliceWithoutOrig-8 7416729 139.0 ns/op 48 B/op 2 allocs/op
  2. BenchmarkNewSliceWithout-8 13280971 103.4 ns/op 64 B/op 1 allocs/op

如果我们使用一个更大的切片:

  1. var s = []string{"a", "b", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "c"}

然后基准测试结果为:

  1. BenchmarkNewSliceWithoutOrig-8 2253637 566.8 ns/op 496 B/op 5 allocs/op
  2. BenchmarkNewSliceWithout-8 5160316 224.3 ns/op 256 B/op 1 allocs/op
英文:

Allocate a big return slice in one step (estimated by the input slice), and don't use append() but assign to individual elements:

  1. func newSliceWithout(s []string, without string) []string {
  2. l, i := make([]string, len(s)), 0
  3. for _, elem := range s {
  4. if elem != without {
  5. l[i] = elem
  6. i++
  7. }
  8. }
  9. return l[:i]
  10. }

Testing it:

  1. x := newSliceWithout([]string{&quot;a&quot;, &quot;b&quot;, &quot;a&quot;, &quot;c&quot;}, &quot;a&quot;)
  2. fmt.Println(x)

which outputs (try it on the Go Playground):

  1. [b c]

Benchmarks

  1. func BenchmarkNewSliceWithoutOrig(b *testing.B) {
  2. for n := 0; n &lt; b.N; n++ {
  3. newSliceWithoutOrig([]string{&quot;a&quot;, &quot;b&quot;, &quot;a&quot;, &quot;c&quot;}, &quot;a&quot;)
  4. }
  5. }
  6. func BenchmarkNewSliceWithout(b *testing.B) {
  7. for n := 0; n &lt; b.N; n++ {
  8. newSliceWithout([]string{&quot;a&quot;, &quot;b&quot;, &quot;a&quot;, &quot;c&quot;}, &quot;a&quot;)
  9. }
  10. }

Result:

  1. BenchmarkNewSliceWithoutOrig-8 7416729 139.0 ns/op 48 B/op 2 allocs/op
  2. BenchmarkNewSliceWithout-8 13280971 103.4 ns/op 64 B/op 1 allocs/op

If we use a bigger slice:

  1. var s = []string{&quot;a&quot;, &quot;b&quot;, &quot;x&quot;, &quot;y&quot;, &quot;z&quot;, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;, &quot;7&quot;, &quot;8&quot;, &quot;9&quot;, &quot;a&quot;, &quot;c&quot;}

Then benchmark results:

  1. BenchmarkNewSliceWithoutOrig-8 2253637 566.8 ns/op 496 B/op 5 allocs/op
  2. BenchmarkNewSliceWithout-8 5160316 224.3 ns/op 256 B/op 1 allocs/op

huangapple
  • 本文由 发表于 2021年5月23日 21:38:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/67660392.html
匿名

发表评论

匿名网友

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

确定