4

我有以下用于实现拼接的代码(即,给定一个完整的字节切片、另一个字节切片部分和一个表示我想用部分覆盖的完整位置的 int pos):

package main

import (
    "fmt"
    "bytes"
)

func main() {
    full := []byte{0,0,0,0,0,0,0}
    part := []byte{1,1,1}

    newFull1 := splice(full, part, 2)
    fmt.Println(newFull1)
    // [0 0 1 1 1 0 0]

    newFull2 := splice(full, part, 3)
    fmt.Println(newFull2)
    // [0 0 0 1 1 1 0]
}

func splice(full []byte, part []byte, pos int) []byte {
    return bytes.Join([][]byte{full[:pos], part, full[len(full[:pos])+len(part):]}, []byte{})
}

基本上,我的方法执行 3 字节切片的连接:完整的第一部分不会被部分覆盖,全部部分,然后是完整的剩余部分。有没有更好/更惯用的方法来做到这一点?我无法在标准库中找到实现此功能的方法。

4

4 回答 4

6

如果您知道部分完全在完整范围内,则可以使用复制功能。

func main() {
    full := []byte{0, 0, 0, 0, 0, 0, 0}
    part := []byte{1, 1, 1}

    copy(full[2:], part)
    fmt.Println(full)
}

操场

这会覆盖完整的。如果您想保留原件,您可以先使用附加功能进行复制。

func main() {
    full := []byte{0, 0, 0, 0, 0, 0, 0}
    part := []byte{1, 1, 1}

    newFull := append([]byte{}, full...)
    copy(newFull[2:], part)
    fmt.Println("newFull:      ", newFull)
    fmt.Println("original full:", full)
}

操场

请注意,这仍然具有原始代码的限制,该部分必须适合完整的范围。

于 2012-11-24T19:10:59.793 回答
1

这是拼接字节切片的另一种变体。该算法类似于 Anton Litvinov 的 stringSplice()。因为 append 函数与输入共享相同的切片,所以必须使用与输入相同长度的副本。这不是由上一个答案中的“beatgammit”完成的,它无法正常工作。

package main

import "fmt"

func sliceSplice(input []byte, start, deleteCount int, item []byte) ([]byte) {
    fmt.Printf("input:      %v start = %d deleteCount = %d item: %v\n", input, start, deleteCount, item)
    cpy := make([]byte, len(input))
    copy(cpy, input)
    fmt.Println("cpy:       ", cpy)
    if start > len(cpy) {
        return append(cpy, item...)
    }
    ret := append(cpy[:start], item...)
    fmt.Println("ret:       ", ret)

    if start+deleteCount > len(cpy) {
        return ret
    }
    fmt.Println("cpy:       ", cpy, "       modified by shared slice 'ret'")
    fmt.Println("input[s+d] ", input[start+deleteCount:], "         not modified")
    return append(ret, input[start+deleteCount:]...)
}

func main() {
    oldFull := []byte{0, 0, 1, 1, 1, 0, 0}
    fmt.Println("oldFull:      ", oldFull, "\n")
    myFull := sliceSplice(oldFull, 3, 0, []byte{2, 2})
    fmt.Println("myFull:       ", myFull, "\n")
    myFull = sliceSplice(oldFull, 3, 1, []byte{2, 2})
    fmt.Println("myFull:       ", myFull, "\n")
    myFull = sliceSplice(oldFull, 3, 4, []byte{2, 2})
    fmt.Println("myFull:       ", myFull, "\n")
    myFull = sliceSplice(oldFull, 3, 6, []byte{2, 2})
    fmt.Println("myFull:       ", myFull, "\n")
    myFull = sliceSplice(oldFull, 7, 0, []byte{2, 2})
    fmt.Println("myFull:       ", myFull, "\n")
    myFull = sliceSplice(oldFull, 9, 6, []byte{2, 2})
    fmt.Println("myFull:       ", myFull, "\n")
}

我还包括了一组测试用例

于 2021-10-11T05:15:25.497 回答
0

为什么不使用append内置?

func splice(full, part []byte, pos int) (ret []byte) {
    ret = append(full[:pos], part...)
    return append(ret, full[pos:]...)
}

这可能不是很快(大量复制),但它非常易读。

于 2012-11-24T19:57:10.610 回答
0

字符串的变体(拆分/拼接/连接)。

func stringSplice(full string, start, deleteCount int, item string) (ret string) {
    if start > len(full) {
        return full + item
    }
    ret = full[:start] + item

    if start+deleteCount > len(full) {
        return ret
    }
    return ret + full[start+deleteCount:]
}
于 2020-12-23T08:26:30.297 回答