Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In place deletion of Golang slice elements

Tags:

slice

in-place

go

I want to delete elements from a collection in an in-place manner. Consider the following snippet:

package main

import "fmt"

type Ints []int

func (xs Ints) Filter() {
    for i := 0; i < len(xs); i++ {
        if xs[i]%2 == 0 { // Or some other filtering function
             xs = append(xs[:i], xs[i+1:]...)
        }
        fmt.Printf("i %+v\n", i)
        fmt.Printf("xs %+v\n", xs)
    }
}

func main() {
    a := Ints([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

    fmt.Printf("initial a %+v\n", a)

    a.Filter()

    fmt.Printf("final a %+v\n", a)
}

http://play.golang.org/p/1nL6Il2Gf1

The surprising result is: final a [1 3 5 7 9 10 10 10 10 10]

I wonder how to do this. I'm pretty sure the receiver needs to be a pointer to Ints. But that messes up the code somewhat (adding *xs everywhere possibly with brackets) but more importantly it yields the same result.

like image 792
harm Avatar asked Jul 14 '14 09:07

harm


People also ask

How do you clear a slice in Go?

Setting the slice to nil is the best way to clear a slice. nil slices in go are perfectly well behaved and setting the slice to nil will release the underlying memory to the garbage collector.

How do you remove the last element from a slice in Golang?

We will follow the below approach to remove the last item: Calculate the length of the slice. Re-slice the original slice to last before element.

How do you remove an element from an array slice?

Remove the first element of an array with slice If you want to remove the first element in an array, you can use Array. prototype. slice() on an array named arr like this: arr. slice(1) .

How do I remove a specific element from a slice in Golang?

To remove the first element, call remove(s, 0), to remove the second, call remove(s, 1), and so on and so forth. Hm, not really. This: s[i] = s[len(s)-1] definitely copies the last element to the element at index i . Then, return s[:len(s)-1] returns the slice without the last element.


2 Answers

I'd do it by moving elements, then resizing the slice, and using a pointer. Something like this:

package main

import "fmt"

type Ints []int

func (xs *Ints) Filter() {
    filterPos := 0
    for i := 0; i < len(*xs); i++ {
        if (*xs)[i]%2 == 0 { // Or some other filtering function
             (*xs)[filterPos] = (*xs)[i]
         filterPos++
        }
    }
    (*xs) = (*xs)[:filterPos]
}

func main() {
    a := Ints([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

    fmt.Printf("initial a %+v\n", a)

    a.Filter()

    fmt.Printf("final a %+v\n", a)
}
like image 148
Not_a_Golfer Avatar answered Oct 08 '22 07:10

Not_a_Golfer


You must use pointer here. If you don't like adding *xs every where just use a temp variable to do all operations then set it back. Here is the code http://play.golang.org/p/eAFkV3Lwh6

like image 22
chendesheng Avatar answered Oct 08 '22 09:10

chendesheng