如何在Go中反转数组?

50 go

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
Run Code Online (Sandbox Code Playgroud)

很难理解func Reverse(数据接口)接口的含义.

如何反转阵列?我不需要排序.

Bra*_*ody 94

老实说,这个很简单,我就这样写出来:

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)
}
Run Code Online (Sandbox Code Playgroud)

http://play.golang.org/p/vkJg_D1yUb

(其他答案很好地解释sort.Interface和如何使用它;所以我不会重复.)


Muh*_*zan 20

通常,要对整数数组进行排序,请将它们包装在一个IntSlice定义方法LenLess,和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}
}
Run Code Online (Sandbox Code Playgroud)

因此,当你写作时sort.Reverse(sort.IntSlice(s)),发生的事情就是你得到了这个新的,"修改过的" IntSlice,它Less取代了它的方法.因此,如果您调用sort.Sort它,哪个调用Less,它将按递减顺序排序.

  • 但是,但是,但是,这也对数组进行了“排序”,不是吗?OP *明确*说他不想对数组进行排序,只想将其反转。这怎么能成为公认的答案呢? (11认同)

Car*_*icz 12

我迟到了两年,但为了好玩和兴趣,我想贡献一个"古怪的"解决方案.

假设任务真的是要反转列表,那么对于原始性能,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]) 
}
Run Code Online (Sandbox Code Playgroud)

输出:

Ints [8 6 7 5 3 0 9] reversed: [9 0 3 5 7 6 8]
Run Code Online (Sandbox Code Playgroud)

同样,这是为了娱乐,而不是生产.它不仅速度慢,而且如果列表太大,它将溢出堆栈.我刚刚进行了测试,它将颠倒100万ints 的列表但崩溃了1000万.

  • 对于好奇的人来说,Go的TCO有限:http://stackoverflow.com/questions/12102675/tail-call-optimization-in-go (2认同)

xia*_*len 8

首先,如果你想要反转数组,那么这样做,

for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
    a[i], a[j] = a[j], a[i]
}
Run Code Online (Sandbox Code Playgroud)

然后,在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]
Run Code Online (Sandbox Code Playgroud)

看看Reverse和Sort的描述

func Reverse(data Interface) Interface
func Sort(data Interface)
Run Code Online (Sandbox Code Playgroud)

排序对数据进行排序.它对data.Len进行一次调用以确定n和O(n*log(n))对data.Less和data.Swap的调用.这种排序不能保证稳定.

因此,如您所知,Sort不仅仅是一种排序算法,您可以将其视为工厂,当您使用Reverse时它只返回反向排序算法,Sort只是在进行排序.


小智 5

如果要反转数组,可以按相反的顺序进行操作.由于语言中没有"反向范围"原语(至少现在还没有),你必须做这样的事情(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()
Run Code Online (Sandbox Code Playgroud)

关于是否很难理解是什么sort.Reverse(data Interface) Interface,在我看到" http://golang.org/src/pkg/sort/sort.go " 的源代码之前,我的想法一直如此.

它只是使得排序所需的比较"反过来".


小智 5

这是更通用的切片反向功能。如果输入不是切片,它将惊慌。

//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)
    }
}
Run Code Online (Sandbox Code Playgroud)


Pra*_*tal 5

这是一个简单的 Go 解决方案,它使用高效(无需额外内存)的方法来反转数组:

i := 0
j := len(nums) - 1
for i < j {
    nums[i], nums[j] = nums[j], nums[i]
    i++
    j--
}
Run Code Online (Sandbox Code Playgroud)

这个想法是,反转数组相当于交换每个元素及其中心的镜像。

https://play.golang.org/p/kLFpom4LH0g