Given
array1 := []int{1, 3, 4, 5} array2 := []int{2, 4, 6, 8}
I want to insert array2[2]
i.e 6
at array1[1]
i.e before 3
so that array1
becomes a slice of {1, 6, 3, 4, 5}
. How can I do it?
Most the techniques I read online involve using the :
operator but results in remaining elements being inserted as well. How can I append single values at an index in a slice?
To add an element to a slice , you can use Golang's built-in append method. append adds elements from the end of the slice. The first parameter to the append method is a slice of type T . Any additional parameters are taken as the values to add to the given slice .
Inserting into slice Golang doesn't support any built-in functions to add items into a slice. To do this, we have to manually implement the insert() method using the append() function.
Let's say that we want to insert an element in an array at position 2. First we need space (length) in order to insert a new element. Appending an element, will make a new space at the end. Then we are able to shift a block of elements from position 2 until the end.
This post will discuss how to insert an item at a specific index in an array using JavaScript. 1. Using Array.prototype.splice () function The splice () method can be used to modify the array by removing or replacing existing elements and/or adding new elements in-place.
The slice () method is used to return an array between two indices. It takes two parameters, one is the beginning index which specifies and the other is the ending index. The first part of the string is extracted using the starting position as 0 and the ending position as the index where the new string has to be inserted.
Set the element at the proper index, using a single assignment. Note that in some special cases (when the slice element is big, like a big struct), it may be faster to append the last element, and then it's enough to copy 1 less elements (because the appended last element is right where it needs to be). This will result in the same slice.
Set the element at the proper index, using a single assignment. Note that in some special cases (when the slice element is big, like a big struct), it may be faster to append the last element, and then it's enough to copy 1 less elements (because the appended last element is right where it needs to be).
A simple append
is what you need:
a = append(a[:index+1], a[index:]...) a[index] = value
Note: len(a) > 0 && index < len(a)
Should len(a) == index
, meaning nil
or empty slice or append after the last element:
a = append(a, value)
Inserting at the index zero for slice of int
s:
a = append([]int{value}, a...)
All in one function:
// 0 <= index <= len(a) func insert(a []int, index int, value int) []int { if len(a) == index { // nil or empty slice or after last element return append(a, value) } a = append(a[:index+1], a[index:]...) // index < len(a) a[index] = value return a }
Usage:
a := []int{10, 30, 40} a = insert(a, 1, 20) fmt.Println(a) // [10 20 30 40]
And for the OP:
slice1 := []int{1, 3, 4, 5} slice2 := []int{2, 4, 6, 8} // slice1 = insert(slice1, 1, slice2[2]) slice1 = append(slice1[:2], slice1[1:]...) slice1[1] = slice2[2] fmt.Println(slice1) // [1 6 3 4 5]
Benchmark:
go version # go version go1.16.3 linux/amd64 make bench go test -benchmem -bench . -args -n 32 # BenchmarkInsert-8 4125085 275.0 ns/op 512 B/op 1 allocs/op # BenchmarkInsert2-8 3778551 316.0 ns/op 512 B/op 1 allocs/op go test -benchmem -bench . -args -n 1000 # BenchmarkInsert-8 198364 5876 ns/op 16384 B/op 1 allocs/op # BenchmarkInsert2-8 205197 7123 ns/op 16384 B/op 1 allocs/op go test -benchmem -bench . -args -n 1000000 # BenchmarkInsert-8 643 1898436 ns/op 10002437 B/op 1 allocs/op # BenchmarkInsert2-8 368 3248385 ns/op 10002436 B/op 1 allocs/op
Code:
func insert(a []int, index int, value int) []int { a = append(a[:index+1], a[index:]...) // Step 1+2 a[index] = value // Step 3 return a } func insert2(a []int, index int, value int) []int { last := len(a) - 1 a = append(a, a[last]) // Step 1 copy(a[index+1:], a[index:last]) // Step 2 a[index] = value // Step 3 return a } func BenchmarkInsert(b *testing.B) { for i := 0; i < b.N; i++ { r = insert(a, 2, 42) } } func BenchmarkInsert2(b *testing.B) { for i := 0; i < b.N; i++ { r = insert2(a, 2, 42) } } var ( n = flag.Int("n", 32, "buffer length") a, r []int ) // We use TestMain to set up the buffer. func TestMain(m *testing.M) { flag.Parse() a = make([]int, *n) os.Exit(m.Run()) }
You may combine the two first steps to one; by using:
a = append(a[:index+1], a[index:]...)
a[index] = value
Which is more efficient, according to the benchmarks.
Simple, efficient and logical way:
array1
has enough capacity (length) to accomodate the new, insertable element. To do that, append a single element using the builting append()
(doesn't matter what that is, it'll get overwritten).copy()
(elements you want to insert before).In code:
array1 := []int{1, 3, 4, 5} array2 := []int{2, 4, 6, 8} array1 = append(array1, 0) // Step 1 copy(array1[2:], array1[1:]) // Step 2 array1[1] = array2[2] // Step 3 fmt.Println(array1)
Output (try it on the Go Playground):
[1 6 3 4 5]
Note that in some special cases (when the slice element is big, like a big struct), it may be faster to append the last element, and then it's enough to copy 1 less elements (because the appended last element is right where it needs to be).
This is how it looks like:
last := len(array1) - 1 array1 = append(array1, array1[last]) // Step 1 copy(array1[2:], array1[1:last]) // Step 2 array1[1] = array2[2] // Step 3
This will result in the same slice. Try this one on the Go Playground.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With