英文:
How do I reverse a slice in go?
问题
如何在Go语言中反转一个任意切片([]interface{}
)?我不想编写Less
和Swap
来使用sort.Reverse
。是否有一种简单的内置方法来实现这个功能?
英文:
How do I reverse an arbitrary slice ([]interface{}
) in Go? I'd rather not have to write Less
and Swap
to use sort.Reverse
. Is there a simple, builtin way to do this?
答案1
得分: 107
在Go 1.21或更高版本中使用slices.Reverse:
slices.Reverse(s)
Go版本1.20及更早版本的答案:
标准库中没有用于反转切片的内置函数。使用for循环来反转切片:
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
在Go 1.18或更高版本中使用类型参数编写通用的反转函数:
func reverse[S ~[]E, E any](s S) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
在Go版本1.8或更高版本中使用reflect.Swapper编写适用于任意切片类型的函数:
func reverse(s interface{}) {
n := reflect.ValueOf(s).Len()
swap := reflect.Swapper(s)
for i, j := 0, n-1; i < j; i, j = i+1, j-1 {
swap(i, j)
}
}
本答案中的函数会原地反转切片。如果不想修改原始切片,在反转切片之前复制切片。
英文:
Use slices.Reverse in Go 1.21 or later:
slices.Reverse(s)
Answers for Go version 1.20 and earlier:
The standard library does not have a built-in function for reversing a slice. Use a for loop to reverse a slice:
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
Use type parameters to write a generic reverse function in Go 1.18 or later:
func reverse[S ~[]E, E any](s S) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
Use reflect.Swapper to write a function that works with arbitrary slice types in Go version 1.8 or later:
func reverse(s interface{}) {
n := reflect.ValueOf(s).Len()
swap := reflect.Swapper(s)
for i, j := 0, n-1; i < j; i, j = i+1, j-1 {
swap(i, j)
}
}
The functions in this answer reverse the slice inplace. If you do not want to modify the original slice, copy the slice before reversing the slice.
答案2
得分: 10
这是另一种可能的反转通用切片的方法(适用于Go 1.18):
// 你可以编辑这段代码!
// 点击这里开始输入。
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int64{10, 5, 15, 20, 1, 100, -1}
ReverseSlice(nums)
fmt.Println(nums)
strs := []string{"hello", "world"}
ReverseSlice(strs)
fmt.Println(strs)
runes := []rune{'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}
ReverseSlice(runes)
for _, r := range runes {
fmt.Print(string(r), " ")
}
}
func ReverseSlice[T comparable](s []T) {
sort.SliceStable(s, func(i, j int) bool {
return i > j
})
}
运行上面的程序应该输出:
[-1 100 1 20 15 5 10]
[world hello]
d l r o w o l l e h
程序已退出。
英文:
Here's another possible way to reverse generic slice (go 1.18)
// You can edit this code!
// Click here and start typing.
package main
import (
"fmt"
"sort"
)
func main() {
nums := []int64{10, 5, 15, 20, 1, 100, -1}
ReverseSlice(nums)
fmt.Println(nums)
strs := []string{"hello", "world"}
ReverseSlice(strs)
fmt.Println(strs)
runes := []rune{'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'}
ReverseSlice(runes)
for _, r := range runes {
fmt.Print(string(r), " ")
}
}
func ReverseSlice[T comparable](s []T) {
sort.SliceStable(s, func(i, j int) bool {
return i > j
})
}
Running the program above should output:
[-1 100 1 20 15 5 10]
[world hello]
d l r o w o l l e h
Program exited.
<kbd>go playground</kbd>
答案3
得分: 7
这将返回一个反转的切片,而不会修改原始切片。
算法使用了官方维基页面上的方法:https://github.com/golang/go/wiki/SliceTricks#reversing
func reverse(s []interface{}) []interface{} {
a := make([]interface{}, len(s))
copy(a, s)
for i := len(a)/2 - 1; i >= 0; i-- {
opp := len(a) - 1 - i
a[i], a[opp] = a[opp], a[i]
}
return a
}
英文:
This will return a reversed slice without modifying the original slice.
Algorithm used from official wiki page: https://github.com/golang/go/wiki/SliceTricks#reversing
func reverse(s []interface{}) []interface{} {
a := make([]interface{}, len(s))
copy(a, s)
for i := len(a)/2 - 1; i >= 0; i-- {
opp := len(a) - 1 - i
a[i], a[opp] = a[opp], a[i]
}
return a
}
答案4
得分: 1
以下是您要翻译的内容:
这是我的代码示例,您可以在playground中运行它。
package main
import (
"fmt"
"reflect"
"errors"
)
func ReverseSlice(data interface{}) {
value := reflect.ValueOf(data)
if value.Kind() != reflect.Slice {
panic(errors.New("data must be a slice type"))
}
valueLen := value.Len()
for i := 0; i <= int((valueLen-1)/2); i++ {
reverseIndex := valueLen - 1 - i
tmp := value.Index(reverseIndex).Interface()
value.Index(reverseIndex).Set(value.Index(i))
value.Index(i).Set(reflect.ValueOf(tmp))
}
}
func main() {
names := []string{"bob", "mary", "sally", "michael"}
ReverseSlice(names)
fmt.Println(names)
}
英文:
There are my code example, you can run it in playground
package main
import (
"fmt"
"reflect"
"errors"
)
func ReverseSlice(data interface{}) {
value := reflect.ValueOf(data)
if value.Kind() != reflect.Slice {
panic(errors.New("data must be a slice type"))
}
valueLen := value.Len()
for i := 0; i <= int((valueLen-1)/2); i++ {
reverseIndex := valueLen - 1 - i
tmp := value.Index(reverseIndex).Interface()
value.Index(reverseIndex).Set(value.Index(i))
value.Index(i).Set(reflect.ValueOf(tmp))
}
}
func main() {
names := []string{"bob", "mary", "sally", "michael"}
ReverseSlice(names)
fmt.Println(names)
}
答案5
得分: 1
这是我正在使用的带有泛型(go 1.18+)的函数。你可以使用它来反转任何类型的切片,甚至是字符串(使用拆分/连接的技巧)。它不会改变原始切片。
package main
import (
"fmt"
"strings"
)
func Reverse[T any](original []T) (reversed []T) {
reversed = make([]T, len(original))
copy(reversed, original)
for i := len(reversed)/2 - 1; i >= 0; i-- {
tmp := len(reversed) - 1 - i
reversed[i], reversed[tmp] = reversed[tmp], reversed[i]
}
return
}
func main() {
a := []string{"a", "b", "c"}
fmt.Println(a, Reverse(a))
b := []uint{0, 1, 2}
fmt.Println(b, Reverse(b))
c := "abc"
fmt.Println(c, strings.Join(Reverse(strings.Split(c, "")), ""))
}
更好的Go Playground:链接
英文:
Here is the function I'm using with generics (go 1.18+). You can use it to reverse any kind of slice or even a string (using the split/join trick). It doesn't change the original slice.
package main
import (
"fmt"
"strings"
)
func Reverse[T any](original []T) (reversed []T) {
reversed = make([]T, len(original))
copy(reversed, original)
for i := len(reversed)/2 - 1; i >= 0; i-- {
tmp := len(reversed) - 1 - i
reversed[i], reversed[tmp] = reversed[tmp], reversed[i]
}
return
}
func main() {
a := []string{"a", "b", "c"}
fmt.Println(a, Reverse(a))
b := []uint{0, 1, 2}
fmt.Println(b, Reverse(b))
c := "abc"
fmt.Println(c, strings.Join(Reverse(strings.Split(c, "")), ""))
}
答案6
得分: 0
这个通用的切片反转函数可以帮助你:
func ReverseSlice[T comparable](s []T) []T {
var r []T
for i := len(s) - 1; i >= 0; i-- {
r = append(r, s[i])
}
return r
}
这个函数可以将给定的切片进行反转。
英文:
This generic slice reversal function should do it for you:
func ReverseSlice[T comparable](s []T) []T {
var r []T
for i := len(s) - 1; i >= 0; i-- {
r = append(r, s[i])
}
return r
}
答案7
得分: 0
func Reverse[T any](array []T) []T {
length := len(array)
result := make([]T, length)
for i, elem := range array {
result[length-1-i] = elem
}
return result
}
func ReverseInPlace[T any](array []T) []T {
length := len(array)
swap := reflect.Swapper(array)
for i := 0; i < length/2; i++ {
swap(i, length-1-i)
}
return array
}
增强了接受的答案。
并进行了测试:
func TestReverse(t *testing.T) {
t.Run("空数组", func(t *testing.T) {
input := []int{}
assert.Equal(t, []int{}, Reverse(input))
assert.Equal(t, []int{}, input)
})
t.Run("反转整数", func(t *testing.T) {
input := []int{1, 2, 3}
assert.Equal(t, []int{3, 2, 1}, Reverse(input))
assert.Equal(t, []int{1, 2, 3}, input)
})
t.Run("反转字符串", func(t *testing.T) {
input := []string{"a", "b", "c"}
assert.Equal(t, []string{"c", "b", "a"}, Reverse(input))
assert.Equal(t, []string{"a", "b", "c"}, input)
})
}
func TestReverseInPlace(t *testing.T) {
t.Run("空数组", func(t *testing.T) {
input := []int{}
assert.Equal(t, []int{}, ReverseInPlace(input))
assert.Equal(t, []int{}, input)
})
t.Run("反转整数", func(t *testing.T) {
input := []int{1, 2, 3}
assert.Equal(t, []int{3, 2, 1}, ReverseInPlace(input))
assert.Equal(t, []int{3, 2, 1}, input)
})
t.Run("反转字符串", func(t *testing.T) {
input := []string{"a", "b", "c"}
assert.Equal(t, []string{"c", "b", "a"}, ReverseInPlace(input))
assert.Equal(t, []string{"c", "b", "a"}, input)
})
}
英文:
func Reverse[T any](array []T) []T {
length := len(array)
result := make([]T, length)
for i, elem := range array {
result[length-1-i] = elem
}
return result
}
func ReverseInPlace[T any](array []T) []T {
length := len(array)
swap := reflect.Swapper(array)
for i := 0; i < length/2; i++ {
swap(i, length-1-i)
}
return array
}
Enhanced the accepted answer.
And tests:
func TestReverse(t *testing.T) {
t.Run("Empty array", func(t *testing.T) {
input := []int{}
assert.Equal(t, []int{}, Reverse(input))
assert.Equal(t, []int{}, input)
})
t.Run("Reverse integers", func(t *testing.T) {
input := []int{1, 2, 3}
assert.Equal(t, []int{3, 2, 1}, Reverse(input))
assert.Equal(t, []int{1, 2, 3}, input)
})
t.Run("Reverse strings", func(t *testing.T) {
input := []string{"a", "b", "c"}
assert.Equal(t, []string{"c", "b", "a"}, Reverse(input))
assert.Equal(t, []string{"a", "b", "c"}, input)
})
}
func TestReverseInPlace(t *testing.T) {
t.Run("Empty array", func(t *testing.T) {
input := []int{}
assert.Equal(t, []int{}, ReverseInPlace(input))
assert.Equal(t, []int{}, input)
})
t.Run("Reverse integers", func(t *testing.T) {
input := []int{1, 2, 3}
assert.Equal(t, []int{3, 2, 1}, ReverseInPlace(input))
assert.Equal(t, []int{3, 2, 1}, input)
})
t.Run("Reverse strings", func(t *testing.T) {
input := []string{"a", "b", "c"}
assert.Equal(t, []string{"c", "b", "a"}, ReverseInPlace(input))
assert.Equal(t, []string{"c", "b", "a"}, input)
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论