fmt.Println(\"Enter position to delete::\")
fmt.Scanln(&pos)
new_arr := make([]int, (len(arr) - 1))
k := 0
for i := 0; i < (len(arr) - 1); {
if i != pos {
Order matters
If you want to keep your array ordered, you have to shift all of the elements at the right of the deleting index by one to the left. Hopefully, this can be done easily in Golang:
func remove(slice []int, s int) []int {
return append(slice[:s], slice[s+1:]...)
}
However, this is inefficient because you may end up with moving all of the elements, which is costy.
Order is not important
If you do not care about ordering, you have the much faster possibility to swap the element to delete with the one at the end of the slice and then return the n-1 first elements:
func remove(s []int, i int) []int {
s[len(s)-1], s[i] = s[i], s[len(s)-1]
return s[:len(s)-1]
}
With the reslicing method, emptying an array of 1 000 000 elements take 224s, with this one it takes only 0.06ns. I suspect that internally, go only changes the length of the slice, without modifying it.
Edit 1
Quick notes based on the comments below (thanks to them !).
As the purpose is to delete an element, when the order does not matter a single swap is needed, the second will be wasted :
func remove(s []int, i int) []int {
s[i] = s[len(s)-1]
// We do not need to put s[i] at the end, as it will be discarded anyway
return s[:len(s)-1]
}
Also, this answer does not perform bounds-checking. It expects a valid index as input. This means that negative values or indices that are greater or equal to len(s) will cause Go to panic. Slices and arrays being 0-indexed, removing the n-th element of an array implies to provide input n-1. To remove the first element, call remove(s, 0), to remove the second, call remove(s, 1), and so on and so forth.
This is a little strange to see but most answers here are dangerous and gloss over what they are actually doing. Looking at the original question that was asked about removing an item from the slice a copy of the slice is being made and then it's being filled. This ensures that as the slices are passed around your program you don't introduce subtle bugs.
Here is some code comparing users answers in this thread and the original post. Here is a go playground to mess around with this code in.
package main
import (
"fmt"
)
func RemoveIndex(s []int, index int) []int {
return append(s[:index], s[index+1:]...)
}
func main() {
all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
removeIndex := RemoveIndex(all, 5)
fmt.Println("all: ", all) //[0 1 2 3 4 6 7 8 9 9]
fmt.Println("removeIndex: ", removeIndex) //[0 1 2 3 4 6 7 8 9]
removeIndex[0] = 999
fmt.Println("all: ", all) //[999 1 2 3 4 6 7 9 9]
fmt.Println("removeIndex: ", removeIndex) //[999 1 2 3 4 6 7 8 9]
}
In the above example you can see me create a slice and fill it manually with numbers 0 to 9. We then remove index 5 from all and assign it to remove index. However when we go to print out all now we see that it has been modified as well. This is because slices are pointers to an underlying array. Writing it out to removeIndex
causes all
to be modified as well with the difference being all
is longer by one element that is no longer reachable from removeIndex
. Next we change a value in removeIndex
and we can see all
gets modified as well. Effective go goes into some more detail on this.
The following example I won't go into but it does the same thing for our purposes. And just illustrates that using copy is no different.
package main
import (
"fmt"
)
func RemoveCopy(slice []int, i int) []int {
copy(slice[i:], slice[i+1:])
return slice[:len(slice)-1]
}
func main() {
all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
removeCopy := RemoveCopy(all, 5)
fmt.Println("all: ", all) //[0 1 2 3 4 6 7 8 9 9]
fmt.Println("removeCopy: ", removeCopy) //[0 1 2 3 4 6 7 8 9]
removeCopy[0] = 999
fmt.Println("all: ", all) //[99 1 2 3 4 6 7 9 9]
fmt.Println("removeCopy: ", removeCopy) //[999 1 2 3 4 6 7 8 9]
}
Looking at the original question it does not modify the slice that it's removing an item from. Making the original answer in this thread the best so far for most people coming to this page.
package main
import (
"fmt"
)
func OriginalRemoveIndex(arr []int, pos int) []int {
new_arr := make([]int, (len(arr) - 1))
k := 0
for i := 0; i < (len(arr) - 1); {
if i != pos {
new_arr[i] = arr[k]
k++
} else {
k++
}
i++
}
return new_arr
}
func main() {
all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
originalRemove := OriginalRemoveIndex(all, 5)
fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
fmt.Println("originalRemove: ", originalRemove) //[0 1 2 3 4 6 7 8 9]
originalRemove[0] = 999
fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
fmt.Println("originalRemove: ", originalRemove) //[999 1 2 3 4 6 7 8 9]
}
As you can see this output acts as most people would expect and likely what most people want. Modification of originalRemove
doesn't cause changes in all
and the operation of removing the index and assigning it doesn't cause changes as well! Fantastic!
This code is a little lengthy though so the above can be changed to this.
package main
import (
"fmt"
)
func RemoveIndex(s []int, index int) []int {
ret := make([]int, 0)
ret = append(ret, s[:index]...)
return append(ret, s[index+1:]...)
}
func main() {
all := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
removeIndex := RemoveIndex(all, 5)
fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 8 9]
fmt.Println("removeIndex: ", removeIndex) //[0 1 2 3 4 6 7 8 9]
removeIndex[0] = 999
fmt.Println("all: ", all) //[0 1 2 3 4 5 6 7 9 9]
fmt.Println("removeIndex: ", removeIndex) //[999 1 2 3 4 6 7 8 9]
}
Almost identical to the original remove index solution however we make a new slice to append to before returning.