Delete items in a slice

I am a complete newbie to Golang, I am trying to remove elements in one fragment based on elements in another fragment. eg

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

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

expected output slice: urlList := []string{"def", "ghi"}

This is what I tried.

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)
    }
}

But it does not work, as I expected. I don’t know what is missing.

+3
source share
3 answers

The problem is that when you remove an item from the original list, all subsequent items are shifted. But the loop rangedoes not know that you have changed the base slice and increment of the index as usual, although in this case it should not, because then you will skip the element.

remove 2 , , ("abc" ) .

- range , , i--, , , -incremented:

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]

:

, + 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)

.

Alternative

, , ( ) , ( - ).

+6

, , , :

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]
+2

.

.

, , , .

Excludeupdates xsin place, so the pointer argument is used. An alternative would be to update the support array xs, but to return a slice from a function, the same as the built-in works 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)
}

This code is O (N + M) at runtime, where N is the length urlsand M is the length remove.

0
source

Source: https://habr.com/ru/post/1614284/


All Articles