http://play.golang.org/p/W70J4GU7nA
s := []int{5, 2, 6, 3, 1, 4}
sort.Reverse(sort.IntSlice(s))
fmt.Println(s)
// 5, 2, 6, 3, 1, 4
很难理解 func Reverse(data Interface) Interface 中的含义。
如何反转数组?我不需要排序。
http://play.golang.org/p/W70J4GU7nA
s := []int{5, 2, 6, 3, 1, 4}
sort.Reverse(sort.IntSlice(s))
fmt.Println(s)
// 5, 2, 6, 3, 1, 4
很难理解 func Reverse(data Interface) Interface 中的含义。
如何反转数组?我不需要排序。
老实说,这个很简单,我就这样写出来:
package main
import "fmt"
func main() {
s := []int{5, 2, 6, 3, 1, 4}
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
fmt.Println(s)
}
http://play.golang.org/p/vkJg_D1yUb
(其他答案很好地解释sort.Interface
了以及如何使用它;所以我不会重复。)
通常,要对整数数组进行排序,您可以将它们包装在 中IntSlice
,它定义了方法Len
、Less
和Swap
。这些方法又被sort.Sort
. 它的作用是sort.Reverse
它采用定义Len
、Less
和的现有类型Swap
,但它用Less
一个始终与底层相反的新方法替换该方法Less
:
type reverse struct {
// This embedded Interface permits Reverse to use the methods of
// another Interface implementation.
Interface
}
// Less returns the opposite of the embedded implementation's Less method.
func (r reverse) Less(i, j int) bool {
return r.Interface.Less(j, i)
}
// Reverse returns the reverse order for data.
func Reverse(data Interface) Interface {
return &reverse{data}
}
所以当你写的时候sort.Reverse(sort.IntSlice(s))
,发生的事情是你得到了这个新的、“修改过的” IntSlice
,它的Less
方法被替换了。因此,如果您调用sort.Sort
它,它调用Less
,它将按降序排序。
我迟到了 2 年,但只是为了乐趣和兴趣,我想贡献一个“古怪”的解决方案。
假设任务确实是反转列表,那么对于原始性能bgp的解决方案可能是无与伦比的。它通过前后交换数组项来简单有效地完成工作,这种操作在数组和切片的随机访问结构中是有效的。
在函数式编程语言中,惯用的方法通常涉及递归。这在 Go 中看起来有点奇怪,并且性能会很差。也就是说,这是一个递归数组反转函数(在一个小测试程序中):
package main
import (
"fmt"
)
func main() {
myInts := []int{ 8, 6, 7, 5, 3, 0, 9 }
fmt.Printf("Ints %v reversed: %v\n", myInts, reverseInts(myInts))
}
func reverseInts(input []int) []int {
if len(input) == 0 {
return input
}
return append(reverseInts(input[1:]), input[0])
}
输出:
Ints [8 6 7 5 3 0 9] reversed: [9 0 3 5 7 6 8]
同样,这是为了娱乐而不是生产。不仅速度慢,而且如果列表太大,它会溢出堆栈。我刚刚测试过,它会反转 100 万int
的列表,但会在 1000 万时崩溃。
首先,如果要反转数组,请这样做,
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
然后,看一下golang.org中Reverse的用法
package main
import (
"fmt"
"sort"
)
func main() {
s := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Sort(sort.Reverse(sort.IntSlice(s)))
fmt.Println(s)
}
// output
// [6 5 4 3 2 1]
并查看 Reverse and Sort 的描述
func Reverse(data Interface) Interface
func Sort(data Interface)
Sort 对数据进行排序。它对 data.Len 进行一次调用以确定 n,然后对 data.Less 和 data.Swap 进行 O(n*log(n)) 调用。不能保证排序是稳定的。
所以,如您所知,Sort 不仅仅是一种排序算法,您可以将其视为一个工厂,当您使用 Reverse 时,它只是返回一个反向排序算法,Sort 只是进行排序。
这是一个更通用的切片反转功能。如果输入不是切片,它会恐慌。
//panic if s is not a slice
func ReverseSlice(s interface{}) {
size := reflect.ValueOf(s).Len()
swap := reflect.Swapper(s)
for i, j := 0, size-1; i < j; i, j = i+1, j-1 {
swap(i, j)
}
}
如果你想反转数组,你可以按相反的顺序遍历它。由于语言中没有“反向范围”原语(至少现在还没有),你必须做这样的事情(http://play.golang.org/p/AhvAfMjs_7):
s := []int{5, 2, 6, 3, 1, 4}
for i := len(s) - 1; i >= 0; i-- {
fmt.Print(s[i])
if i > 0 {
fmt.Print(", ")
}
}
fmt.Println()
关于是否很难理解是什么sort.Reverse(data Interface) Interface
,我是这么想的,直到我看到“ http://golang.org/src/pkg/sort/sort.go ”的源代码。
它只是使排序所需的比较“反过来”。
这是一个简单的 Go 解决方案,它使用一种高效(无额外内存)的方法来反转数组:
i := 0
j := len(nums) - 1
for i < j {
nums[i], nums[j] = nums[j], nums[i]
i++
j--
}
这个想法是,反转一个数组相当于交换每个元素及其在中心的镜像。
这是另一种方法
func main() {
example := []int{1, 25, 3, 5, 4}
sort.SliceStable(example, func(i, j int) bool {
return true
})
fmt.Println(example)
}
func Reverse(data Interface) Interface
这意味着它需要一个sort.Interface
并返回另一个sort.Interface
——它实际上并没有做任何排序。例如,如果你传入sort.IntSlice
(本质上是一个[]int
可以传递给sort.Sort
它以按升序对其进行排序的 a),你将得到一个新sort.Interface
的,它以降序对 int 进行排序。
顺便说一句,如果您单击文档中的函数名称,它会直接链接到. Reverse
如您所见,它只是包装了sort.Interface
您传入的,因此从返回的值Reverse
获取原始的所有方法sort.Interface
。唯一不同的方法是返回与嵌入的方法Less
相反的方法。有关嵌入字段的详细信息,请参阅语言规范的这一部分。Less
sort.Interface
用相同的元素但以相反的顺序替换切片的内容:
for i := len(a)/2-1; i >= 0; i-- { opp := len(a)-1-i a[i], a[opp] = a[opp], a[i] }
同样的事情,除了有两个索引:
for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 { a[left], a[right] = a[right], a[left] }
这是一种使用方法append
:
package main
import "fmt"
func main() {
a := []int{10, 20, 30, 40, 50}
for n := len(a) - 2; n >= 0; n-- {
a = append(a[:n], append(a[n + 1:], a[n])...)
}
fmt.Println(a)
}
绘制步骤:
10 20 30 40 50
10 20 30 50 40
10 20 50 40 30
10 50 40 30 20
50 40 30 20 10
要反转一个数组,迭代到它的中点,并用它的“镜像元素”交换每个元素:
func main() {
xs := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
itemCount := len(xs)
for i := 0; i < itemCount/2; i++ {
mirrorIdx := itemCount - i -1
xs[i], xs[mirrorIdx] = xs[mirrorIdx], xs[i]
}
fmt.Printf("xs: %v\n", xs)
}
这是我的解决方案。
package main
import (
"fmt"
)
func main() {
var numbers = [10]int {1,2,3,4,5,6,7,8,9,10}
var reverseNumbers [10]int
j:=0
for i:=len(numbers)-1; i>=0 ; i-- {
reverseNumbers[j]=numbers[i]
j++
}
fmt.Println(reverseNumbers)
}
这是我反转数组的解决方案:
func reverse_array(array []string) []string {
lenx := len(array) // lenx holds the original array length
reversed_array := make([]string, lenx) // creates a slice that refer to a new array of length lenx
for i := 0; i < lenx; i++ {
j := lenx - (i + 1) // j initially holds (lenx - 1) and decreases to 0 while i initially holds 0 and increase to (lenx - 1)
reversed_array[i] = array[j]
}
return reversed_array
}
您可以在 go playground上尝试此解决方案
package main
import "fmt"
func main() {
array := []string{"a", "b", "c", "d"}
fmt.Println(reverse_array(array)) // prints [d c b a]
}
不要反转它,让它保持现在,然后向后迭代它。