Golang deletes an element of a slice and eliminates zero values in the slice

Time:2022-1-3

Look at the code~


func remove(slice []interface{}, elem interface{}) []interface{}{
    if len(slice) == 0 {
        return slice
    }
    for i, v := range slice {
        if v == elem {
            slice = append(slice[:i], slice[i+1:]...)
            return remove(slice,elem)
            break
        }
    }
    return slice
}
func removeZero(slice []interface{}) []interface{}{
    if len(slice) == 0 {
        return slice
    }
    for i, v := range slice {
        if ifZero(v) {
            slice = append(slice[:i], slice[i+1:]...)
            return removeZero(slice)
            break
        }
    }
    return slice
}
//Judge whether a value is zero. Only string, float, int, time and their respective pointers are supported. "%" and "%%" also belong to the category of zero value. The scenario is a like statement
func IfZero(arg interface{}) bool {
    if arg == nil {
        return true
    }
    switch v := arg.(type) {
    case int, int32, int16, int64:
        if v == 0 {
            return true
        }
    case float32:
        r:=float64(v)
        return math.Abs(r-0)<0.0000001
    case float64:
        return math.Abs(v-0)<0.0000001
    case string:
        if v == "" || v == "%%" || v == "%" {
            return true
        }
    case *string, *int, *int64, *int32, *int16, *int8, *float32, *float64, *time.Time:
        if v == nil {
            return true
        }
    case time.Time:
        return v.IsZero()
    default:
        return false
    }
    return false
}

Supplement: golang deletes elements with specific conditions in slice, optimized version

Write two methods to delete specific elements in a slice, and make a performance comparison. Record it here.

Assuming that our slice has 0 and 1, we want to delete all 0. Here are three methods:

The first method:


func DeleteSlice(a []int) []int{
 for i := 0; i < len(a); i++ {
  if a[i] == 0 {
   a = append(a[:i], a[i+1:]...)
   i--
  }
 }
 return a
}

Explanation: common methods are used to delete the elements in slice. Note that when deleting, the following elements move forward and I should move back one bit.

The second method:


func DeleteSlice1(a []int) []int {
 ret := make([]int, 0, len(a))
 for _, val := range a {
  if val == 1 {
   ret = append(ret, val)
  }
 }
 return ret
}

Explanation: this method is the easiest to understand. Reuse a slice to filter out unreasonable. The disadvantage is that another slice needs to be opened up. The advantage is that it is easy to understand and does not operate the original slice.

The third method:


func DeleteSlice2(a []int) []int{
 j := 0
 for _, val := range a {
  if val == 1 {
   a[j] = val
   j++
  }
 }
 return a[:j]
}

Explanation: here, an index is used to record the position where the next valid element should be. All elements are traversed. When a valid element is encountered, the index is added by one, otherwise it is not added. The final position of the index is the next position of all valid elements. Finally, just do an interception. This method will modify the original slice.

Here, the performance of the three methods is tested, and the test code is as follows:


package main 
import (
 "testing"
)
 
func handle(data []int) {
 return
}
const N = 100
 
func getSlice()[]int {
 a := []int{}
 for i := 0; i < N; i++ {
  if i % 2 == 0 {
   a = append(a, 0)
  } else {
   a = append(a, 1)
  }
 }
 return a
}
 
func BenchmarkDeleteSlice(b *testing.B) {
 for i := 0; i < b.N; i++ {
   data := DeleteSlice(getSlice())
   handle(data)
 }
}
 
func BenchmarkDeleteSlice1(b *testing.B) {
 for i := 0; i < b.N; i++ {
  data := DeleteSlice1(getSlice())
  handle(data)
 }
}
 
func BenchmarkDeleteSlice2(b *testing.B) {
 for i := 0; i < b.N; i++ {
  data := DeleteSlice2(getSlice())
  handle(data)
 }
}

The test results are as follows (slice size is 100):

Increase the slice size for testing (the slice size is 10000):

Continue to increase (slice size is 100000)

Slice size is 10 ^ 6:

It can be seen that:

The first method is about twice as slow as the second and third methods when the slice size is small. However, when the slice size becomes larger, the performance decreases significantly.

The gap between the second method and the third method is basically the same order of magnitude, but the third method is slightly faster. However, when the slice size increases to 10 ^ 6, the advantages of the third method appear.

The above is my personal experience. I hope I can give you a reference, and I hope you can support developpaer. If you have any mistakes or don’t consider completely, please don’t hesitate to comment.

Recommended Today

Vue2 technology finishing 3 – Advanced chapter – update completed

3. Advanced chapter preface Links to basic chapters:https://www.cnblogs.com/xiegongzi/p/15782921.html Link to component development:https://www.cnblogs.com/xiegongzi/p/15823605.html 3.1. Custom events of components 3.1.1. Binding custom events There are two implementation methods here: one is to use v-on with vuecomponent$ Emit implementation [PS: this method is a little similar to passing from child to parent]; The other is to use ref […]