[英]How do I reverse a slice in go?
如何反转 Go 中的任意切片 ( []interface{}
)? 我宁愿不必编写Less
和Swap
来使用sort.Reverse
。 有没有一种简单的内置方法可以做到这一点?
标准库没有用于反转切片的内置函数。 使用 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)
}
}
此答案中的功能将切片就地反转。 如果您不想修改原始切片,请在反转切片之前复制该切片。
这将返回一个反向切片而不修改原始切片。
来自官方 wiki 页面的算法: 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
}
这是反转通用切片的另一种可能方法(转到 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
})
}
运行上面的程序应该输出:
[-1 100 1 20 15 5 10]
[world hello]
d l r o w o l l e h
Program exited.
有我的代码示例,你可以在操场上运行
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)
}
这个通用切片反转 function 应该为你做:
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
}
这是我与泛型一起使用的函数(转到 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, "")), ""))
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.