Go中的惯用语拼接

时间:2017-03-12 20:09:45

标签: for-loop go slice

我检查了现有的answer,但它与我的情况不太相似。

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

问题: 如果在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)

2 个答案:

答案 0 :(得分: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]

答案 1 :(得分:0)

如果切片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]