Tuesday 28 November 2017

go - Remove elements in slice

itemprop="text">

I am complete newbie in Golang, I am
trying to remove elements in one slice based on the elements in another
slice.
e.g.



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




elements to
remove 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's
not working as I expected. I don't know what I am missing.



Answer




The problem is that when you remove an
element from the original list, all subsequent elements are
shifted. But the range loop doesn't know
that you changed the underlying slice and will increment the index as usual, even though
in this case it shouldn't because then you skip an
element.




And since the
remove list contains 2 elements which are right
next to each other
in the original list, the second one
("abc" in this case) will not be checked and will not be
removed.



One possible solution is not to use
range in the outer loop, and when you remove an element, you
manually decrease the index i--
because continuing with the next iteration it will get
auto-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)



Output:



[def
ghi]


Note:



Since
the outer loop contains nothing after the inner loop, you can replace the label+continue
with a simple
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)


Try
it on Go
Playground
.




Alternative



An
alternative to this would be for the outer loop to go downward, so no need to manually
decrease (or increase) the index variable because the shifted elements are not affected
(already processed due to the downward direction).



No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...