82

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

It is hard to understand what it means in func Reverse(data Interface) Interface .

How do I reverse an array? I do not need to sort.

kostix
  • 51,517
  • 14
  • 93
  • 176
  • See http://stackoverflow.com/questions/18343208/how-to-reverse-sort-a-slice-of-integer-golang. I think you need to use `Sort` to do it easily. – Intermernet Oct 08 '13 at 05:33
  • 6
    This makes me want to throw go out the window. Seriously, I need a loop to reverse an array? The odds of me writing that incorrectly in the first attempt because of an offset-by-one error are astronomical. The code is more verbose and harder to read. And the accepted answer sorts the array, even when OP explicitly says no need to sort. – Peter V. Mørch May 18 '22 at 06:38
  • This is described on the wiki: https://github.com/golang/go/wiki/SliceTricks#reversing – ayke Dec 18 '22 at 21:31

20 Answers20

160

Honestly this one is simple enough that I'd just write it out like this:

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

(The other answers do a good job of explaining sort.Interface and how to use it; so I won't repeat that.)

Brad Peabody
  • 10,917
  • 9
  • 44
  • 63
31

Normally, to sort an array of integers you wrap them in an IntSlice, which defines the methods Len, Less, and Swap. These methods are in turn used by sort.Sort. What sort.Reverse does is that it takes an existing type that defines Len, Less, and Swap, but it replaces the Less method with a new one that is always the inverse of the underlying 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}
}

So when you write sort.Reverse(sort.IntSlice(s)), whats happening is that you're getting this new, 'modified' IntSlice that has it's Less method replaced. So if you call sort.Sort on it, which calls Less, it will get sorted in decreasing order.

Muhammad Faizan
  • 944
  • 6
  • 11
  • 9
    But, but, but, this also *sorts* the array, doesn't it? The OP *explicity* said he didn't want to sort the array, only reverse it. How can this be the accepted answer? – Peter V. Mørch May 18 '22 at 06:01
21

I'm 2 years late, but just for fun and interest I'd like to contribute an "oddball" solution.

Assuming the task really is to reverse a list, then for raw performance bgp's solution is probably unbeatable. It gets the job done simply and effectively by swapping array items front to back, an operation that's efficient in the random-access structure of arrays and slices.

In Functional Programming languages, the idiomatic approach would often involve recursion. This looks a bit strange in Go and will have atrocious performance. That said, here's a recursive array reversal function (in a little test program):

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]) 
}

Output:

Ints [8 6 7 5 3 0 9] reversed: [9 0 3 5 7 6 8]

Again, this is for fun and not production. Not only is it slow, but it will overflow the stack if the list is too large. I just tested, and it will reverse a list of 1 million ints but crashes on 10 million.

Community
  • 1
  • 1
Carl Smotricz
  • 66,391
  • 18
  • 125
  • 167
  • 4
    For the curious, there's only limited TCO in Go: http://stackoverflow.com/questions/12102675/tail-call-optimization-in-go – Lloeki Apr 21 '15 at 14:23
  • FP style +1. Also FP likes expressions not statements. With an `if` use an `else`. See https://stackoverflow.com/a/63762078/12817546 and "Functional Programming, Simplified". –  Sep 06 '20 at 08:28
  • Similar but without recursion: https://stackoverflow.com/a/72986510/463758 – balki Jul 14 '22 at 20:50
16

First of all, if you want to reverse the array, do like this,

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

Then, look at the usage of Reverse in golang.org

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]

And look at the description of Reverse and Sort

func Reverse(data Interface) Interface
func Sort(data Interface)

Sort sorts data. It makes one call to data.Len to determine n, and O(n*log(n)) calls to data.Less and data.Swap. The sort is not guaranteed to be stable.

So, as you know, Sort is not just a sort algorithm, you can view it as a factory, when you use Reverse it just return a reversed sort algorithm, Sort is just doing the sorting.

xiaoyusilen
  • 181
  • 2
  • 7
7

This is a more generic slice reverse function. It will panic if input is not a slice.

//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)
    }
}
Chris
  • 661
  • 6
  • 7
Yongke
  • 318
  • 3
  • 5
5

If you want to reverse the array, you can just go through it in reverse order. Since there is no "reverse range" primitive in the language (at least not yet), you must do something like this (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()

Regarding whether it is hard to understand what sort.Reverse(data Interface) Interface does, I thought the same until I saw the source code from "http://golang.org/src/pkg/sort/sort.go".

It just makes the comparisons required for the sorting to be made "the other way around".

5

Here is a simple Go solution that uses an efficient (no extra memory) approach to reverse an array:

i := 0
j := len(nums) - 1
for i < j {
    nums[i], nums[j] = nums[j], nums[i]
    i++
    j--
}

The idea is that reversing an array is equivalent to swapping each element with its mirror image across the center.

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

Pranjal Mittal
  • 10,772
  • 18
  • 74
  • 99
3

Here is another way to do it

func main() {
    example := []int{1, 25, 3, 5, 4}
    sort.SliceStable(example, func(i, j int) bool {
        return true
    })
    fmt.Println(example)
}

https://play.golang.org/p/-tIzPX2Ds9z

Tarion
  • 16,283
  • 13
  • 71
  • 107
manugupt1
  • 2,337
  • 6
  • 31
  • 39
  • I think this is not the correct way, I've not been able to find a reason, but the below slice does not get reversed []int{48,44,37,40,14,45,8,38,12,31} Which is a little weird. – nJoshi Jun 21 '18 at 06:55
  • @nJoshi if you use `sort.SliceStable` then your array gets reversed. The answer should be updated to use `sort.SliceStable` – killachaos Jul 02 '18 at 01:57
  • What I am not able to understand even with stable sort is that the order is not guaranteed in cases of equality conditions. The example that @nJoshi provided has all elements unique. This is from the godoc : SliceStable sorts the provided slice given the provided less function while keeping the original order of equal elements. – manugupt1 Jul 02 '18 at 13:29
  • i cant tell if this wrong or not. https://play.golang.org/p/wNuwvvpdxMu –  Aug 17 '21 at 15:27
2
func Reverse(data Interface) Interface

This means that it takes a sort.Interface and returns another sort.Interface -- it doesn't actually doing any sorting itself. For example, if you pass in sort.IntSlice (which is essentially a []int that can be passed to sort.Sort to sort it in ascending order) you'll get a new sort.Interface which sorts the ints in descending order instead.

By the way, if you click on the function name in the documentation, it links directly to the source for Reverse. As you can see, it just wraps the sort.Interface that you pass in, so the value returned from Reverse gets all the methods of the original sort.Interface. The only method that's different is the Less method which returns the opposite of the Less method on the embedded sort.Interface. See this part of the language spec for details on embedded fields.

Tyler
  • 21,762
  • 11
  • 61
  • 90
1

From Golang wiki SliceTricks:

To replace the contents of a slice with the same elements but in reverse order:

for i := len(a)/2-1; i >= 0; i-- {
  opp := len(a)-1-i
  a[i], a[opp] = a[opp], a[i]
}

The same thing, except with two indices:

for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
  a[left], a[right] = a[right], a[left]
}
cakraww
  • 2,493
  • 28
  • 30
  • idk why it was downvoted. it is good to me. And it does a few less operations than `for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {` –  Aug 17 '21 at 15:30
1

Simple solution without involving math. Like this solution, this is inefficient as it does too much allocation and garbage collection. Good for non-critical code where clarity is more important than performance. Playground: https://go.dev/play/p/dQGwrc0Q9ZA

arr := []int{1, 3, 4, 5, 6}
var rev []int
for _, n := range arr {
    rev = append([]int{n}, rev...)
}
fmt.Println(arr)
fmt.Println(rev)
balki
  • 26,394
  • 30
  • 105
  • 151
1

Its very simple if you want to print reverse array

Use Index from length doing i--

ex.

a := []int{5, 4, 12, 7, 15, 9}
    for i := 0; i <= len(a)-1; i++ {
        fmt.Println(a[len(a)-(i+1)])
    }

https://go.dev/play/p/bmyFh7-_VCZ

0

To reverse an array in place, iterate to its mid-point, and swap each element with its "mirror element":

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)
}

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

Martin Probst
  • 9,497
  • 6
  • 31
  • 33
0

Here is a method using 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)
}

Drawing of the steps:

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
Zombo
  • 1
  • 62
  • 391
  • 407
0

This answer is mainly for those beginners who wish to write this code using only one variable in the for loop instead of using two variables (like i & j).

package main

import "fmt"

func main() {
array := []int{45, 17, 43, 67, 21, 4, 97, 44, 54, 98, 665}
fmt.Println("initial array:", array)
loop_iteration := len(array)
if len(array)%2 == 0 {
    loop_iteration = (len(array) / 2) - 1
  } else {
    loop_iteration = int(len(array) / 2)  //This will give the lower integer value of that float number.
    }
for i := 0; i <= loop_iteration; i++ {
    array[i], array[(len(array)-1)-i] = array[(len(array)-1)-i], array[i]
    }
fmt.Println("reverse array:", array)
}
0

https://go.dev/play/p/bVp0x7v6Kbs

package main

import (
    "fmt"
)

func main() {
    arr := []int{1, 2, 3, 4, 5}
    fmt.Println(reverseArray(arr))
}

func reverseArray(arr []int) []int {
    reversed := make([]int, len(arr))
    j := 0
    for i := len(arr) - 1; i >= 0; i-- {
        reversed[j] = arr[i]
        j++
    }
    return reversed
}
Sam
  • 11
  • 2
0

Using generic so you can reverse any type arrays

func reverseArray[T any](arr []T) []T {
    result := make([]T, len(arr))
    length := len(arr)
    for index := range arr {
        result[(length-1)-index] = arr[index]
    }
    return result
}
-1

Here is my solution.

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)
}
Alyona Yavorska
  • 569
  • 2
  • 14
  • 20
-2

Here is my solution to reversing an array:

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
}

You can try this solution on the go playground the go playground

package main

import "fmt"

func main() {
    array := []string{"a", "b", "c", "d"}

    fmt.Println(reverse_array(array)) // prints [d c b a]
}
doncredas
  • 161
  • 7
-3

Do not reverse it, leave it as now and then just iterate it backwards.

Mario
  • 1,661
  • 13
  • 22