3 回答
TA贡献1155条经验 获得超0个赞
问题在于,当您从原始列表中删除一个元素时,所有后续元素都将被shift。但是range循环不知道您更改了底层切片并且会像往常一样增加索引,即使在这种情况下它不应该因为您跳过一个元素。
并且由于该remove列表包含 2 个在原始列表中彼此相邻的元素,因此"abc"不会检查第二个(在这种情况下)也不会被删除。
一种可能的解决方案是不range在外循环中使用,当您删除一个元素时,您手动减少索引,i--因为继续下一次迭代它将自动增加:
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]
笔记:
由于外循环在内循环之后不包含任何内容,因此您可以用简单的 替换 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上试试。
选择
对此的替代方法是外循环向下,因此无需手动减少(或增加)索引变量,因为移位的元素不受影响(由于向下方向已被处理)。
TA贡献1966条经验 获得超4个赞
也许创建一个新切片更简单,它只包含您想要的元素,例如:
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个赞
在迭代切片时修改切片时必须小心。
这是通过在迭代数据的同时压缩数据来从切片中删除元素的常用方法。
它还对排除元素使用映射而不是切片,这在排除项的数量很大时提供了效率。
Excludexs就地更新,这就是使用指针参数的原因。另一种方法是更新 的后备数组xs,但以与内置函数相同的方式从函数返回切片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 关注
- 276 浏览
添加回答
举报