在Go语言中,如何反转一个任意的分片([]interface{})?我宁愿不写Less和Swap来使用sort.Reverse,有没有一个简单的内置方法来实现这个功能?
[]interface{}
Less
Swap
sort.Reverse
crcmnpdw1#
标准库没有内置的反转切片的函数,使用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) } }
Run the code on the Go playground .本答案中的函数在原处反转切片。如果不想修改原始切片,请在反转切片之前复制切片。
mzmfm0qo2#
下面是另一种反转通用切片的方法(参见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.
go playground
vyu0f0g13#
这将返回反转切片,而不修改原始切片。使用来自官方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 }
polkgigr4#
这是我的代码示例,可以在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) }
xtfmy6hx5#
这个通用的切片反转功能可以帮您完成:
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 }
ne5o7dgx6#
下面是我在generic(go 1.18+)中使用的函数,你可以用它来反转任何类型的切片,甚至是一个字符串(使用split/join技巧),它不会改变原始切片。
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, "")), "")) }
Better Go Playground
6条答案
按热度按时间crcmnpdw1#
标准库没有内置的反转切片的函数,使用for循环来反转切片:
在Go语言1.18或更高版本中,使用类型参数编写一个泛型反转函数:
在Go语言1.8或更高版本中,使用reflect.swapper来编写一个可以处理任意切片类型的函数:
Run the code on the Go playground .
本答案中的函数在原处反转切片。如果不想修改原始切片,请在反转切片之前复制切片。
mzmfm0qo2#
下面是另一种反转通用切片的方法(参见1.18)
运行上述程序应输出:
go playground
vyu0f0g13#
这将返回反转切片,而不修改原始切片。
使用来自官方wiki页面的算法:https://github.com/golang/go/wiki/SliceTricks#reversing
polkgigr4#
这是我的代码示例,可以在playground中运行
xtfmy6hx5#
这个通用的切片反转功能可以帮您完成:
ne5o7dgx6#
下面是我在generic(go 1.18+)中使用的函数,你可以用它来反转任何类型的切片,甚至是一个字符串(使用split/join技巧),它不会改变原始切片。
Better Go Playground