Home  >  Article  >  Backend Development  >  How to delete elements from a slice in go language

How to delete elements from a slice in go language

青灯夜游
青灯夜游Original
2022-12-20 10:55:026586browse

Deletion method: 1. Intercept the slice to delete the specified element, the syntax is "append(a[:i], a[i 1:]...)". 2. Create a new slice, filter out the elements to be deleted and assign them to the new slice. 3. Use a subscript index to record the position where a valid element should be; traverse all elements, and when a valid element is encountered, move it to index and increase the index by one; the final index position is the next position of all valid elements , and finally make an interception.

How to delete elements from a slice in go language

The operating environment of this tutorial: Windows 7 system, GO version 1.18, Dell G3 computer.

Go does not provide special syntax or functions for deleting slice elements. You need to use the characteristics of the slice itself to delete elements.

There are generally the following methods to delete specified elements in a slice. This article uses []int as an example to give the specific implementation.

1. Interception method (modify the original slice)

Here, interception of the slice is used to delete the specified element. Note that when deleting, the following elements will be moved forward, so the subscript i should be moved one position to the left.

// DeleteSlice1 删除指定元素。
func DeleteSlice1(a []int, elem int) []int {
	for i := 0; i < len(a); i++ {
		if a[i] == elem {
			a = append(a[:i], a[i+1:]...)
			i--
		}
	}
	return a
}

2. Copy method (without changing the original slice)

This method is the easiest to understand. Reuse a slice and delete it. Elements are filtered out. The disadvantage is that it needs to open up space for another slice. The advantage is that it is easy to understand and does not modify the original slice.

// DeleteSlice2 删除指定元素。
func DeleteSlice2(a []int, elem int) []int {
	tmp := make([]int, 0, len(a))
	for _, v := range a {
		if v != elem {
			tmp = append(tmp, v)
		}
	}
	return tmp
}

3. Shift method (modify the original slice)

##3.1 Method 1

Use a subscript index to record the position where the next valid element should be. Traverse all elements. When a valid element is encountered, move it to index and increase index by one. The final index position is the next position of all valid elements, and finally an interception is enough. This method will modify the original slice.

This method can be seen as an improvement on the first method of interception, because each time an element needs to be moved, the performance is better.

// DeleteSlice3 删除指定元素。
func DeleteSlice3(a []int, elem int) []int {
	j := 0
	for _, v := range a {
		if v != elem {
			a[j] = v
			j++
		}
	}
	return a[:j]
}

3.2 Method 2

Creates a slice, but shares the underlying array of the original slice. In this way, there is no need to allocate additional memory space, and modifications can be made directly on the original slice.

// DeleteSlice4 删除指定元素。
func DeleteSlice4(a []int, elem int) []int {
	tgt := a[:0]
	for _, v := range a {
		if v != elem {
			tgt = append(tgt, v)
		}
	}
	return tgt
}

4. Performance comparison

Suppose our slice has 0 and 1, and we want to delete all 0.

Here we test slices with lengths of 10, 100, and 1000 to compare the performance differences of the above four implementations.

The generated slice function is as follows:

func getSlice(n int) []int {
	a := make([]int, 0, n)
	for i := 0; i < n; i++ {
		if i%2 == 0 {
			a = append(a, 0)
			continue
		}
		a = append(a, 1)
	}
	return a
}

The benchmark test code is as follows:

func BenchmarkDeleteSlice1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = DeleteSlice1(getSlice(10), 0)
	}
}
func BenchmarkDeleteSlice2(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = DeleteSlice2(getSlice(10), 0)
	}
}
func BenchmarkDeleteSlice3(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = DeleteSlice3(getSlice(10), 0)
	}
}
func BenchmarkDeleteSlice4(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_ = DeleteSlice4(getSlice(10), 0)
	}
}

The test results are as follows:

The original slice length is 10:

go test -bench=. main/slice
goos: windows
goarch: amd64
pkg: main/slice
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkDeleteSlice1-8         17466486                65.07 ns/op
BenchmarkDeleteSlice2-8         14897282                85.22 ns/op
BenchmarkDeleteSlice3-8         21952129                50.78 ns/op
BenchmarkDeleteSlice4-8         22176390                54.68 ns/op
PASS
ok      main/slice      5.427s

The original slice length is 100:

BenchmarkDeleteSlice1-8          1652146               762.1 ns/op
BenchmarkDeleteSlice2-8          2124237               578.4 ns/op
BenchmarkDeleteSlice3-8          3161318               359.9 ns/op
BenchmarkDeleteSlice4-8          2714158               423.7 ns/op

The original slice length is 1000:

BenchmarkDeleteSlice1-8            56067             21915 ns/op
BenchmarkDeleteSlice2-8           258662              5007 ns/op
BenchmarkDeleteSlice3-8           432049              2724 ns/op
BenchmarkDeleteSlice4-8           325194              3615 ns/op

5. Summary

Judging from the benchmark test results, the method with the best performance is the shift method, and the first implementation method is the better. The least performant and most commonly used method is the interception method. As the slice length increases, the performance difference between the above four deletion methods will become more obvious.

In actual use, we can choose according to the different scenarios. If you cannot modify the original slice using the copy method, you can modify the original slice using the first implementation method of the shift method.

【Related recommendations:

Go video tutorial, Programming teaching

The above is the detailed content of How to delete elements from a slice in go language. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn