【问题标题】:Idiomatic Splice in GoGo 中的惯用拼接
【发布时间】:2017-08-02 19:29:18
【问题描述】:

我检查了一个现有的answer,但它与我的情况不同。

我需要根据Compare 函数在索引处提取一个元素并在运行时跳出for 循环。

问题: 如果在 0 index 找到要采摘的元素,index-1 将抛出范围错误,如果 index+1 大于 len(elements),则类似。

问题:实现上述目标的最佳简洁方法是什么?

for index, element := range elements {
    if element.Compare() == true {
        elements = append(elements[:index-1], elements[index+1:]...)
        break
    }
}

尝试

for index, element := range elements {
    if element.Compare() == true {
        if len(elements) > 1 {
            elements = append(elements[:index-1], elements[index+1:]...)
        } else if len(elements) == 1 {
            delete(elements, 0)
        }
        break
    }
}

尝试 2 Playground 有任何改进/建议吗?

这个想法是将剩余的元素从开头复制到索引,然后复制之后的任何元素。

var elements = []string {"a", "b", "c", "d"}
fmt.Println(elements)
for index, element := range elements {
    if element == "c" {
        var temp = elements[:index]
        for i := index + 1; i<len(elements); i++ {
            temp = append(temp, elements[i])
        }
        elements = temp
        break
    }
}
fmt.Println(elements)

【问题讨论】:

  • 你的问题是什么?
  • 从切片中提取元素的最佳方法是什么
  • 您是否尝试删除单个元素?那个在索引index?
  • 是的,只有单个元素,然后打破

标签: for-loop go slice


【解决方案1】:

slice expression 中的高索引是专有

这意味着你的例子有缺陷,也不需要特殊处理。

正确的切片表达式是:

elements = append(elements[:index], elements[index+1:]...)

如果 index 是第一个元素 (0),那么 elements[:0] 将是一个空切片。

如果index 是最后一个元素(len-1),那么elements[index+1:] 也将是一个空切片,因为index+1 将等于切片的长度。所以解决方法很简单:

for index, element := range elements {
    if element.Compare() {
        elements = append(elements[:index], elements[index+1:]...)
        break
    }
}

为了在 Go Playground 上演示它,让我们用一个简单的索引检查替换 Compare() 方法:

for _, idxToRemove := range []int{0, 2, 4} {
    s := []int{0, 1, 2, 3, 4}
    for i := range s {
        if i == idxToRemove {
            s = append(s[:i], s[i+1:]...)
            break
        }
    }
    fmt.Println(idxToRemove, ":", s)
}

输出(在Go Playground上试试):

0 : [1 2 3 4]
2 : [0 1 3 4]
4 : [0 1 2 3]

【讨论】:

    【解决方案2】:

    如果切片s 已排序且len(s) 很大,则使用二分搜索查找x。例如,

    package main
    
    import (
        "fmt"
        "sort"
    )
    
    func pluck(s []string, x string) []string {
        i := sort.SearchStrings(s, x)
        if i >= 0 && i < len(s) && s[i] == x {
            s = append(s[:i], s[i+1:]...)
        }
        return s
    }
    
    func main() {
        s := []string{"a", "b", "c", "d"}
        fmt.Println(s)
        s = pluck(s, "b")
        fmt.Println(s)
    }
    

    输出:

    [a b c d]
    [a c d]
    

    如果不需要保留切片s的顺序,则切换元素。例如,

    package main
    
    import "fmt"
    
    func pluck(s []string, x string) []string {
        for i, v := range s {
            if v == x {
                s[i] = s[len(s)-1]
                s = s[:len(s)-1]
                break
            }
        }
        return s
    }
    
    func main() {
        s := []string{"a", "b", "c", "d"}
        fmt.Println(s)
        s = pluck(s, "b")
        fmt.Println(s)
    }
    

    输出:

    [a b c d]
    [a d c]
    

    否则,拼接切片 s 元素。例如,

    package main
    
    import "fmt"
    
    func pluck(s []string, x string) []string {
        for i, v := range s {
            if v == x {
                s = append(s[:i], s[i+1:]...)
                break
            }
        }
        return s
    }
    
    func main() {
        s := []string{"a", "b", "c", "d"}
        fmt.Println(s)
        s = pluck(s, "b")
        fmt.Println(s)
    }
    

    输出:

    [a b c d]
    [a c d]
    

    【讨论】:

      【解决方案3】:

      我不确定这是否是惯用的,但这很好用:

      package main
      
      import "fmt"
      
      func splice(start, count int, items []string) (ret []string) {
          ret = make([]string, len(items)-count)
          copy(ret, items[:start])
          copy(ret[start:], items[start+count:])
          return
      }
      
      func main() {
          s := []string{"a", "b", "c", "d"}
          fmt.Println(s)
          s = splice(1, 2, s)
          fmt.Println(s)
      }
      
      

      去游乐场:https://play.golang.org/p/UNtdtw77sEQ

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-24
        • 1970-01-01
        • 2014-07-13
        • 1970-01-01
        • 2016-11-05
        相关资源
        最近更新 更多