3 回答

TA貢獻1798條經驗 獲得超7個贊
訂單事項
如果要保持數組有序,則必須將刪除索引右側的所有元素向左移動一位。希望這可以在 Golang 中輕松完成:
func remove(slice []int, s int) []int {
return append(slice[:s], slice[s+1:]...)
}
但是,這是低效的,因為您最終可能會移動所有元素,這很昂貴。
順序不重要
如果您不關心排序,則可以更快地用切片末尾的元素替換要刪除的元素,然后返回 n-1 個第一個元素:
func remove(s []int, i int) []int {
s[i] = s[len(s)-1]
return s[:len(s)-1]
}
使用 reslicing 方法,清空一個包含 1 000 000 個元素的數組需要 224 秒,而這個只需要 0.06 ns。
這個答案不執行bounds-checking。它需要一個有效的索引作為輸入。這意味著大于或等于初始值的負值或索引len(s)將導致 Go 恐慌。
切片和數組索引為 0,刪除數組的第 n 個元素意味著提供輸入n-1。要刪除第一個元素,請調用remove(s, 0),要刪除第二個元素,請調用remove(s, 1),依此類推。

TA貢獻1783條經驗 獲得超4個贊
從 Slice 中刪除一個元素(這稱為“重新切片”):
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) //[0 1 2 3 4 5 6 7 8 9]
all = RemoveIndex(all, 5)
fmt.Println(all) //[0 1 2 3 4 6 7 8 9]
}

TA貢獻1951條經驗 獲得超3個贊
這有點奇怪,但這里的大多數答案都是危險的,并且掩蓋了他們實際在做什么。查看有關從切片中刪除項目的原始問題,正在制作切片的副本,然后將其填充。這可確保當切片在您的程序中傳遞時,您不會引入細微的錯誤。
這是一些比較用戶在此線程和原始帖子中的答案的代碼。這是一個可以在其中處理此代碼的go playground。
基于附加的刪除
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]
}
在上面的示例中,您可以看到我創建了一個切片并用數字 0 到 9 手動填充它。然后我們從所有中刪除索引 5 并將其分配給刪除索引。但是,當我們現在打印所有內容時,我們看到它也已被修改。這是因為切片是指向底層數組的指針。寫出來,以removeIndex原因all被修改以及與該差值all是由不再從可到達的一個元件更長removeIndex。接下來我們改變一個值removeIndex,我們可以看到也all被修改了。Effective go對此進行了更詳細的介紹。
下面的例子我不會進入,但它為我們的目的做了同樣的事情。并且只是說明使用副本沒有什么不同。
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]
}
問題原始答案
查看原始問題,它不會修改要從中刪除項目的切片。對于大多數訪問此頁面的人來說,使該線程中的原始答案是迄今為止最好的。
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]
}
如您所見,此輸出的行為符合大多數人的預期,并且可能是大多數人想要的。的修改originalRemove不會導致更改all,刪除索引并分配它的操作也不會導致更改!極好的!
這段代碼有點長,所以上面可以改成這樣。
一個正確的答案
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]
}
幾乎與原始的刪除索引解決方案相同,但是我們在返回之前創建了一個新的切片來追加。
- 3 回答
- 0 關注
- 580 瀏覽
添加回答
舉報