如何将 Golang 中切片中的一个值移动到最后一个位置?

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

How to move a value in a slice to the last position in Golang?

问题

我想知道如何在Golang中将切片元素正确地移动到切片的最后一个位置。

例如:

  1. func main() {
  2. slc := []int{1,2,3,4,5}
  3. fmt.Println(shiftEnd(slc,2))
  4. }
  5. func shiftEnd(s []int, x int) []int {
  6. return append(s[x:],s[:x]...)
  7. }

这将得到 [3,4,5,1,2],我想知道如何得到 [1,3,4,5,2]
所以接收到的值将被移动到末尾,但其他值将保持原来的顺序。

Playground

英文:

I was wondering on how to properly move a slice element to the last position of a slice in Golang.

e.g:

  1. func main() {
  2. slc := []int{1,2,3,4,5}
  3. fmt.Println(shiftEnd(slc,2))
  4. }
  5. func shiftEnd(s []int, x int) []int {
  6. return append(s[x:],s[:x]...)
  7. }

This will result in [3,4,5,1,2] I was wondering how to receive [1,3,4,5,2].
So the received value, will be moved to the end, but the others will be kept in the same order.

Playground

答案1

得分: 2

这是使用泛型的版本,可以处理任意类型的切片。

  1. // 将 s[x] 处的元素移到切片末尾。
  2. // 直接修改 `s`
  3. func shiftEnd[T any](s []T, x int) []T {
  4. if x < 0 {
  5. return s
  6. }
  7. if x >= len(s)-1 {
  8. return s
  9. }
  10. tmp := s[x]
  11. // 由于新切片的容量适合,所以不需要分配内存
  12. s = append(s[:x], s[x+1:]...)
  13. // 追加到末尾
  14. // 由于新切片的容量适合,所以不需要分配内存
  15. s = append(s, tmp)
  16. return s
  17. }

示例:https://go.dev/play/p/J7TmafgNwm3

  1. func main() {
  2. test := []int{1, 2, 3, 4, 5, 6}
  3. fmt.Printf("before: %#v\n", test)
  4. out := shiftEnd(test, 2)
  5. fmt.Printf("after: %#v\nresult: %#v\n", test, out)
  6. }

输出:

  1. before: []int{1, 2, 3, 4, 5, 6}
  2. after: []int{1, 2, 4, 5, 6, 3}
  3. result: []int{1, 2, 4, 5, 6, 3}
英文:

Here you are, the versoin with generics. Can handle the slice of any type.

  1. // Relocates element at s[x] to the end ov the slice.
  2. // Modifies `s` in place
  3. func shiftEnd[T any](s []T, x int) []T {
  4. if x &lt; 0 {
  5. return s
  6. }
  7. if x &gt;= len(s)-1 {
  8. return s
  9. }
  10. tmp := s[x]
  11. // No allocation since the new slice fits capacity
  12. s = append(s[:x], s[x+1:]...)
  13. // append to the end
  14. // no allocation, the new slice fits the capacity
  15. s = append(s, tmp)
  16. return s
  17. }

Example: https://go.dev/play/p/J7TmafgNwm3

  1. func main() {
  2. test := []int{1, 2, 3, 4, 5, 6}
  3. fmt.Printf(&quot;before: %#v\n&quot;, test)
  4. out := shiftEnd(test, 2)
  5. fmt.Printf(&quot;after: %#v\nresult: %#v\n&quot;, test, out)
  6. }

Output:

  1. before: []int{1, 2, 3, 4, 5, 6}
  2. after: []int{1, 2, 4, 5, 6, 3}
  3. result: []int{1, 2, 4, 5, 6, 3}

答案2

得分: 0

我正在为您翻译以下内容:

我正在使用这个代码片段解决方案进行尝试,似乎对我所寻找的功能有效。

  1. func main() {
  2. s := []int{1, 2, 3, 4, 5}
  3. fmt.Println(shiftEnd(s, 2))
  4. }
  5. func shiftEnd(s []int, x int) []int {
  6. if len(s) < 1 {
  7. fmt.Println("No Enought Values")
  8. return s
  9. }
  10. if s[len(s)-1] == x {
  11. fmt.Println("Already in the end")
  12. return s
  13. }
  14. return append(append(s[:x-1], s[x:]...), x)
  15. }

Playground

英文:

I was playing with this snippet solution, seems to work for what I was looking for.

  1. func main() {
  2. s := []int{1, 2, 3, 4, 5}
  3. fmt.Println(shiftEnd(s, 2))
  4. }
  5. func shiftEnd(s []int, x int) []int {
  6. if len(s) &lt; 1 {
  7. fmt.Println(&quot;No Enought Values&quot;)
  8. return s
  9. }
  10. if s[len(s)-1] == x {
  11. fmt.Println(&quot;Already in the end&quot;)
  12. return s
  13. }
  14. return append(append(s[:x-1], s[x:]...), x)
  15. }

Playground

答案3

得分: 0

请参考以下评论:

  1. func shiftEnd(s []int, x int) []int {
  2. if len(s) <= 1 {
  3. return s
  4. }
  5. t := s[x] // 保存要移动的值
  6. copy(s[x:], s[x+1:]) // 向下移动元素
  7. s[len(s)-1] = t // 在末尾设置值
  8. return s
  9. }

使用类型参数编写一个可以与任何切片类型一起使用的函数:

  1. func shiftEnd[S ~[]E, E any](s S, x int) S {
  2. if len(s) <= 1 {
  3. return s
  4. }
  5. t := s[x] // 保存要移动的值
  6. copy(s[x:], s[x+1:]) // 向下移动元素
  7. s[len(s)-1] = t // 在末尾设置值
  8. return s
  9. }

我对 OP 的问题有点困惑,因为 OP 的答案中将 x 既用作元素值又用作元素索引。本答案假设 OP 只打算将 x 用作索引。

英文:

See commentary for details:

  1. func shiftEnd(s []int, x int) []int {
  2. if len(s) &lt;= 1 {
  3. return s
  4. }
  5. t := s[x] // save value to move
  6. copy(s[x:], s[x+1:]) // shift elements down
  7. s[len(s)-1] = t // set value at end
  8. return s
  9. }

Use type parameters to write a function that works with any slice type:

  1. func shiftEnd[S ~[]E, E any](s S, x int) S {
  2. if len(s) &lt;= 1 {
  3. return s
  4. }
  5. t := s[x] // save value to move
  6. copy(s[x:], s[x+1:]) // shift elements down
  7. s[len(s)-1] = t // set value at end
  8. return s
  9. }

https://go.dev/play/p/CSWP6_4e0Ys

I am little confused about what OP is asking because OP's answer uses x as both an element value and an element index. This answer assumes that OP intended to use x as an index only.

huangapple
  • 本文由 发表于 2022年10月21日 12:43:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/74148841.html
匿名

发表评论

匿名网友

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

确定