在Go语言中将切片中的元素从一个位置移动到另一个位置。

huangapple go评论92阅读模式
英文:

Moving an slice item from one position to another in go

问题

我正在尝试将一个项目从一个位置移动到另一个位置,这个项目是在一个切片中。以下是代码和输出结果:

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]

我的错误在哪里?

英文:

I' trying to move an item from one position to another inside a slice. 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)

This produces to following output:

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] 

But I would expect the output be like this:

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] 

Where is my fault?

答案1

得分: 9

我之前遇到过同样的问题,我解决了如下:

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

英文:

I had the same issue before and I solved as:

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

答案2

得分: 3

问题在于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)	
}

(请注意,我还添加了val变量,而不是将1硬编码为要插入的值。)

英文:

The problem is that newSlice is not a distinct copy of slice--they reference the same underlying array.

So when you assign to newSlice, you're modifying the underlying array, and thus slice, too.

To remedy this, you need to make an explicit copy:

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 that I've also added the val variable, rather than hardcoding 1 as the value to be inserted.)

答案3

得分: 1

这是一个简单的右移示例,没有使用复制,但包含一个循环来展示实际上都是指针。

package main

import "fmt"

func main() {
	s := []int{2, 3, 5, 7, 11, 13}
	for _, e := range s {
		// 每次都会向右移动2个位置
		fmt.Println(e, shiftRight(s, e))
	}
}

func shiftRight(s []int, e int) []int {
	if len(s) > 1 { // 如果只有一个元素,无法进行右移
		// 遍历切片,找到要右移的元素
		for i, item := range s {
			if item == e {
				if i == len(s)-1 {
					break // 已经在末尾,无法再右移
				}
				s[i] = s[i+1]
				s[i+1] = item
				break
			}
		}
	}
	return s
}

Playground

英文:

Here's a simple shift right example without copy but also includes a loop showing how it's all really pointers.

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
}

答案4

得分: 0

如果你需要带有泛型的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)
}
英文:

If you need the omotto's version with generics:

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)
}

huangapple
  • 本文由 发表于 2017年4月26日 00:52:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/43616676.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定