在go中将切片项从一个位置移动到另一个位置

g0czyy6m  于 2023-08-01  发布在  Go
关注(0)|答案(4)|浏览(128)

我试图在一个切片中将一个项目从一个位置移动到另一个位置。Go Playground

indexToRemove := 1
indexWhereToInsert := 4

slice := []int{0,1,2,3,4,5,6,7,8,9}    

slice = append(slice[:indexToRemove], slice[indexToRemove+1:]...)
fmt.Println("slice:", slice)    

newSlice := append(slice[:indexWhereToInsert], 1)
fmt.Println("newSlice:", newSlice)

slice = append(newSlice, slice[indexWhereToInsert:]...)
fmt.Println("slice:", slice)

字符串
这产生以下输出:

slice: [0 2 3 4 5 6 7 8 9]
newSlice: [0 2 3 4 1]
slice: [0 2 3 4 1 1 6 7 8 9]


但我希望输出是这样的:

slice: [0 2 3 4 5 6 7 8 9]
newSlice: [0 2 3 4 1]
slice: [0 2 3 4 1 **5** 6 7 8 9]


我的错在哪里?

5vf7fwbs

5vf7fwbs1#

我以前遇到过同样的问题,我解决了:

func insertInt(array []int, value int, index int) []int {
    return append(array[:index], append([]int{value}, array[index:]...)...)
}

func removeInt(array []int, index int) []int {
    return append(array[:index], array[index+1:]...)
}

func moveInt(array []int, srcIndex int, dstIndex int) []int {
    value := array[srcIndex]
    return insertInt(removeInt(array, srcIndex), value, dstIndex)
}

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

    fmt.Println("slice: ", slice)

    slice = insertInt(slice, 2, 5)  
    fmt.Println("slice: ", slice)

    slice = removeInt(slice, 5) 
    fmt.Println("slice: ", slice)

    slice = moveInt(slice, 1, 4) 
    fmt.Println("slice: ", slice)
}

字符串
https://play.golang.org/p/Sfu1VsySieS

klh5stk1

klh5stk12#

问题是newSlice不是slice的不同副本--它们引用相同的底层数组。
因此,当你赋值给newSlice时,你修改了底层数组,因此也修改了slice
要解决这个问题,您需要创建一个显式副本:
Playground

package main

import (
    "fmt"
)

func main() {

    indexToRemove := 1
    indexWhereToInsert := 4

    slice := []int{0,1,2,3,4,5,6,7,8,9}

    val := slice[indexToRemove]

    slice = append(slice[:indexToRemove], slice[indexToRemove+1:]...)
    fmt.Println("slice:", slice)    

    newSlice := make([]int, indexWhereToInsert+1)
    copy(newSlice,slice[:indexWhereToInsert])
    newSlice[indexWhereToInsert]=val
    fmt.Println("newSlice:", newSlice)
    fmt.Println("slice:", slice)

    slice = append(newSlice, slice[indexWhereToInsert:]...)
    fmt.Println("slice:", slice)    
}

字符串
(Note我还添加了val变量,而不是将1硬编码为要插入的值。

w6lpcovy

w6lpcovy3#

这里有一个简单的右移例子,没有复制,但也包括一个循环,显示它是如何真正的指针。
Playground

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}
    for _, e := range s {
        // Will always shift 2 as it's been shifted each time
        fmt.Println(e, shiftRight(s, e))
    }
}

func shiftRight(s []int, e int) []int {
    if len(s) > 1 { // No where to shift to if 1 item
        // Go through the slice finding the item to shift
        for i, item := range s {
            if item == e {
                if i == len(s)-1 {
                    break // already at the end, can't shift any further
                }
                s[i] = s[i+1]
                s[i+1] = item
                break
            }
        }
    }
    return s
}

字符串

zbdgwd5y

zbdgwd5y4#

如果你需要omotto的泛型版本:

func insertInt[T any](array []T, value T, index int) []T {
    return append(array[:index], append([]T{value}, array[index:]...)...)
}

func removeInt[T any](array []T, index int) []T {
    return append(array[:index], array[index+1:]...)
}

func moveElement[T any](array []T, srcIndex int, dstIndex int) []T {
    value := array[srcIndex]
    return insertInt(removeInt(array, srcIndex), value, dstIndex)
}

字符串

相关问题