3 回答

TA貢獻1155條經驗 獲得超0個贊
問題在于,當您從原始列表中刪除一個元素時,所有后續(xù)元素都將被shift。但是range循環(huán)不知道您更改了底層切片并且會像往常一樣增加索引,即使在這種情況下它不應該因為您跳過一個元素。
并且由于該remove列表包含 2 個在原始列表中彼此相鄰的元素,因此"abc"不會檢查第二個(在這種情況下)也不會被刪除。
一種可能的解決方案是不range在外循環(huán)中使用,當您刪除一個元素時,您手動減少索引,i--因為繼續(xù)下一次迭代它將自動增加:
urlList := []string{"test", "abc", "def", "ghi"}
remove := []string{"abc", "test"}
loop:
for i := 0; i < len(urlList); i++ {
url := urlList[i]
for _, rem := range remove {
if url == rem {
urlList = append(urlList[:i], urlList[i+1:]...)
i-- // Important: decrease index
continue loop
}
}
}
fmt.Println(urlList)
輸出:
[def ghi]
筆記:
由于外循環(huán)在內循環(huán)之后不包含任何內容,因此您可以用簡單的 替換 label+continue break:
urlList := []string{"test", "abc", "def", "ghi"}
remove := []string{"abc", "test"}
for i := 0; i < len(urlList); i++ {
url := urlList[i]
for _, rem := range remove {
if url == rem {
urlList = append(urlList[:i], urlList[i+1:]...)
i-- // Important: decrease index
break
}
}
}
fmt.Println(urlList)
在Go Playground上試試。
選擇
對此的替代方法是外循環(huán)向下,因此無需手動減少(或增加)索引變量,因為移位的元素不受影響(由于向下方向已被處理)。

TA貢獻1966條經驗 獲得超4個贊
也許創(chuàng)建一個新切片更簡單,它只包含您想要的元素,例如:
package main
import "fmt"
func main() {
urlList := []string{"test", "abc", "def", "ghi"}
remove := []string{"abc", "test"}
new_list := make([]string, 0)
my_map := make(map[string]bool, 0)
for _, ele := range remove {
my_map[ele] = true
}
for _, ele := range urlList {
_, is_in_map := my_map[ele]
if is_in_map {
fmt.Printf("Have to ignore : %s\n", ele)
} else {
new_list = append(new_list, ele)
}
}
fmt.Println(new_list)
}
操場
結果:
Have to ignore : test
Have to ignore : abc
[def ghi]

TA貢獻1851條經驗 獲得超5個贊
在迭代切片時修改切片時必須小心。
這是通過在迭代數(shù)據(jù)的同時壓縮數(shù)據(jù)來從切片中刪除元素的常用方法。
它還對排除元素使用映射而不是切片,這在排除項的數(shù)量很大時提供了效率。
Excludexs就地更新,這就是使用指針參數(shù)的原因。另一種方法是更新 的后備數(shù)組xs,但以與內置函數(shù)相同的方式從函數(shù)返回切片append。
package main
import "fmt"
func Exclude(xs *[]string, excluded map[string]bool) {
w := 0
for _, x := range *xs {
if !excluded[x] {
(*xs)[w] = x
w++
}
}
*xs = (*xs)[:w]
}
func mapFromSlice(ex []string) map[string]bool {
r := map[string]bool{}
for _, e := range ex {
r[e] = true
}
return r
}
func main() {
urls := []string{"test", "abc", "def", "ghi"}
remove := mapFromSlice([]string{"abc", "test"})
Exclude(&urls, remove)
fmt.Println(urls)
}
此代碼在運行時為 O(N+M),其中 N 是 的長度,urlsM 是 的長度remove。
- 3 回答
- 0 關注
- 309 瀏覽
添加回答
舉報