dounang1974
dounang1974
2018-09-27 23:46

Python的list.pop()方法的Go惯用法是什么?

已采纳

In Python, I have the following:

i = series.index(s) # standard Python list.index() function
tmp = series.pop(i)
blah = f(tmp)
series.append(tmp)

In converting this to Go, I am looking for a similar way of retrieving an item from a slice by index, doing something with it, then putting the original item at the end of my slice.

From here, I have arrived at the following:

i = Index(series, s) // my custom index function...
tmp, series = series[i], series[i+1:]
blah := f(tmp)
series = append(series, tmp)

But this fails at the end of lists:

panic: runtime error: slice bounds out of range

How would I idiomatically translate this slice.pop() into Go?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

5条回答

  • douzhajie7168 douzhajie7168 3年前

    The "Cut" trick in the linked document does what you want:

    xs := []int{1, 2, 3, 4, 5}
    
    i := 0 // Any valid index, however you happen to get it.
    x := xs[i]
    xs = append(xs[:i], xs[i+1:]...)
    // Now "x" is the ith element and "xs" has the ith element removed.
    

    Note that if you try to make a one-liner out of the get-and-cut operations you'll get unexpected results due to the tricky behavior of multiple assignments in which functions are called before other expressions are evaluated:

    i := 0
    x, xs := xs[i], append(xs[:i], xs[i+1:]...)
    // XXX: x=2, xs=[]int{2, 3, 4, 5}
    

    You can work around by wrapping the element access operation in any function call, such as the identity function:

    i := 0
    id := func(z int) { return z }
    x, xs := id(xs[i]), append(xs[:i], xs[i+1:]...)
    // OK: x=1, xs=[]int{2, 3, 4, 5}
    

    However, at that point it's probably more clear to use separate assignments.

    For completeness, a "cut" function and its usage could look like this:

    func cut(i int, xs []int) (int, []int) {
      y := xs[i]
      ys := append(xs[:i], xs[i+1:]...)
      return y, ys
    }
    
    t, series := cut(i, series)
    f(t)
    series = append(series, t)
    
    点赞 评论 复制链接分享
  • dongtao6842 dongtao6842 3年前

    You can declaretype intSlice []int and you can declare method pop() using that pointer receiver: func (l *intSlice) pop() int. Then you can call .pop() on instance of intSlice object. This becomes stylistically more similar to Python.

    package main
    
    import (
        "fmt"
    )
    
    type intSlice []int
    
    func (l *intSlice) pop() int {
        length := len(*l)
        lastEle := (*l)[length-1]
        *l = (*l)[:length-1]
        return lastEle
    }
    
    func main() {
    
        mySlice := intSlice{1, 2, 3, 4, 5, 6}
    
        popped := mySlice.pop()
    
        fmt.Println(popped)
        fmt.Println(mySlice)
    
        popped = mySlice.pop()
    
        fmt.Println(popped)
        fmt.Println(mySlice)
    
    }
    

    Result:

    6
    [1 2 3 4 5]
    5
    [1 2 3 4]
    

    Go Playground

    点赞 评论 复制链接分享
  • dongxun3424 dongxun3424 3年前

    If you want to write a function that does pop() in a similar way to python then you'll have to pass in a pointer to the object so the object can be modified, as pop both returns the value and alters the list

    func pop(alist *[]int) int {
       f:=len(*alist)
       rv:=(*alist)[f-1]
       *alist=append((*alist)[:f-1])
       return rv
    }
    
    func main() {
    n:=[]int{1,2,3,4,5}
    fmt.Println(n)
    last:=pop(&n)
    fmt.Println("last is",last)
    fmt.Printf("list of n is now %v
    ", n)
    
    点赞 评论 复制链接分享
  • doushen8391 doushen8391 3年前

    I'd do something similar to what paulsm4 suggested:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        a := []int{1,2,3,4,5}
        i,b := pop(a)
        fmt.Println(i,b) // 5 [1 2 3 4]
    }
    
    func pop(a []int) (int,[]int) {
        return a[len(a)-1],a[:len(a)-1]
    }
    

    Go playground

    点赞 评论 复制链接分享
  • douzhuo5671 douzhuo5671 3年前

    I'm not sure there's a direct equivalent of "pop()" ... but you can do something like this:

    A Tour of Go

    Slices can be created with the built-in make function; this is how you create dynamically-sized arrays.

    The make function allocates a zeroed array and returns a slice that refers to that array:

    a := make([]int, 5) // len(a)=5

    To specify a capacity, pass a third argument to make:

    b := make([]int, 0, 5) // len(b)=0, cap(b)=5

    b = b[:cap(b)] // len(b)=5, cap(b)=5

    b = b[1:] // len(b)=4, cap(b)=4

    See also:

    点赞 评论 复制链接分享

相关推荐