猿问

删除切片中的元素

我是 Golang 的完全新手,我试图根据另一个切片中的元素删除一个切片中的元素。例如


输入切片: urlList := []string{"test", "abc", "def", "ghi"}


要删除切片的元素: remove := []string{"abc", "test"}


预期输出切片: urlList := []string{"def", "ghi"}


这是我尝试过的。


func main() {


    urlList := []string{"test", "abc", "def", "ghi"}

    remove := []string{"abc", "test"}

loop:

    for i, url := range urlList {

        for _, rem := range remove {

            if url == rem {

                urlList = append(urlList[:i], urlList[i+1:]...)

                continue loop

            }

        }

    }

    for _, v := range urlList {

        fmt.Println(v)

    }

}

但它并没有像我预期的那样工作。我不知道我错过了什么。


温温酱
浏览 277回答 3
3回答

白衣非少年

问题在于,当您从原始列表中删除一个元素时,所有后续元素都将被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++ {&nbsp; &nbsp; url := urlList[i]&nbsp; &nbsp; for _, rem := range remove {&nbsp; &nbsp; &nbsp; &nbsp; if url == rem {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; urlList = append(urlList[:i], urlList[i+1:]...)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i-- // Important: decrease index&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue loop&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}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++ {&nbsp; &nbsp; url := urlList[i]&nbsp; &nbsp; for _, rem := range remove {&nbsp; &nbsp; &nbsp; &nbsp; if url == rem {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; urlList = append(urlList[:i], urlList[i+1:]...)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i-- // Important: decrease index&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}fmt.Println(urlList)在Go Playground上试试。选择对此的替代方法是外循环向下,因此无需手动减少(或增加)索引变量,因为移位的元素不受影响(由于向下方向已被处理)。

慕标5832272

也许创建一个新切片更简单,它只包含您想要的元素,例如:package mainimport "fmt"func main() {&nbsp; &nbsp; urlList := []string{"test", "abc", "def", "ghi"}&nbsp; &nbsp; remove := []string{"abc", "test"}&nbsp; &nbsp; new_list := make([]string, 0)&nbsp; &nbsp; my_map := make(map[string]bool, 0)&nbsp; &nbsp; for _, ele := range remove {&nbsp; &nbsp; &nbsp; &nbsp; my_map[ele] = true&nbsp; &nbsp; }&nbsp; &nbsp; for _, ele := range urlList {&nbsp; &nbsp; &nbsp; &nbsp; _, is_in_map := my_map[ele]&nbsp; &nbsp; &nbsp; &nbsp; if is_in_map {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("Have to ignore : %s\n", ele)&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new_list = append(new_list, ele)&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(new_list)}操场结果:Have to ignore : testHave to ignore : abc[def ghi]

江户川乱折腾

在迭代切片时修改切片时必须小心。这是通过在迭代数据的同时压缩数据来从切片中删除元素的常用方法。它还对排除元素使用映射而不是切片,这在排除项的数量很大时提供了效率。Excludexs就地更新,这就是使用指针参数的原因。另一种方法是更新 的后备数组xs,但以与内置函数相同的方式从函数返回切片append。package mainimport "fmt"func Exclude(xs *[]string, excluded map[string]bool) {&nbsp; &nbsp; w := 0&nbsp; &nbsp; for _, x := range *xs {&nbsp; &nbsp; &nbsp; &nbsp; if !excluded[x] {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (*xs)[w] = x&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w++&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; *xs = (*xs)[:w]}func mapFromSlice(ex []string) map[string]bool {&nbsp; &nbsp; r := map[string]bool{}&nbsp; &nbsp; for _, e := range ex {&nbsp; &nbsp; &nbsp; &nbsp; r[e] = true&nbsp; &nbsp; }&nbsp; &nbsp; return r}func main() {&nbsp; &nbsp; urls := []string{"test", "abc", "def", "ghi"}&nbsp; &nbsp; remove := mapFromSlice([]string{"abc", "test"})&nbsp; &nbsp; Exclude(&urls, remove)&nbsp; &nbsp; fmt.Println(urls)}此代码在运行时为 O(N+M),其中 N 是 的长度,urlsM 是 的长度remove。
随时随地看视频慕课网APP

相关分类

Go
我要回答