web-dev-qa-db-fra.com

Comment inverser un tableau dans 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

Il est difficile de comprendre ce que cela signifie dans l’interface func Reverse (interface de données).

Comment inverser un tableau? Je n'ai pas besoin de trier.

40
user2671513

Normalement, pour trier un tableau d'entiers, vous les enroulez dans une IntSlice, qui définit les méthodes Len, Less et Swap. Ces méthodes sont à leur tour utilisées par sort.Sort. Ce que sort.Reverse fait, c'est qu'il faut un type existant qui définit Len, Less et Swap, mais il remplace la méthode Less par un nouveau qui est toujours l'inverse du Less sous-jacent:

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

Ainsi, lorsque vous écrivez sort.Reverse(sort.IntSlice(s)), ce qui se passe, c’est que vous obtenez cette nouvelle méthode IntSlice 'modifiée' dont la méthode Less est remplacée. Donc, si vous appelez sort.Sort, qui appelle Less, il sera trié par ordre décroissant.

18
Muhammad Faizan

Honnêtement, celui-ci est assez simple pour que je l’écrive comme ceci:

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

(Les autres réponses expliquent bien Interface et son utilisation; je ne vais donc pas répéter cela.)

80
Brad Peabody

Je suis 2 ans en retard, mais juste pour le plaisir et l'intérêt, je voudrais apporter une solution "bizarre".

En supposant que la tâche consiste réellement à inverser une liste, la solution de bgp pour les performances brutes est probablement imbattable. Pour effectuer le travail simplement et efficacement, vous devez permuter les éléments d'un tableau, opération qui se révèle efficace dans la structure à accès aléatoire des tableaux et des tranches.

Dans les langages de programmation fonctionnels, l'approche idiomatique implique souvent une récursion. Cela semble un peu étrange dans Go et aura des performances atroces. Cela dit, voici une fonction d’inversion de tableau récursive (dans un petit programme de test):

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

Sortie:

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

Encore une fois, c'est pour le plaisir et non pour la production. Non seulement il est lent, mais il débordera de la pile si la liste est trop longue. Je viens de tester, et il va inverser une liste de 1 million ints mais tombe en panne sur 10 millions.

8
Carl Smotricz

Tout d’abord, si vous voulez inverser le tableau, faites comme ça,

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

Ensuite, regardez l’utilisation de Reverse dans 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]

Et regardez la description de Reverse et Sort

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

Trier les données de tri. Il fait un appel à data.Len pour déterminer n et O (n * log (n)) appels à data.Less et data.Swap. Le tri n'est pas garanti pour être stable.

Donc, comme vous le savez, le tri n'est pas simplement un algorithme de tri, vous pouvez le voir comme une usine. Lorsque vous l'utilisez, l'inverse, il suffit de renvoyer un algorithme de tri inversé, le tri se fait simplement.

6
xiaoyusilen

Si vous souhaitez inverser le tableau, vous pouvez simplement le parcourir dans l'ordre inverse. Comme il n'y a pas de primitive "plage inversée" dans la langue (du moins pas encore), vous devez faire quelque chose comme ceci ( 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()

Quant à savoir s’il est difficile de comprendre ce que sort.Reverse(data Interface) Interface fait, j’ai pensé la même chose jusqu’à ce que je voie le code source de " http://golang.org/src/pkg/sort/sort.go ".

Il effectue simplement les comparaisons requises pour que le tri soit effectué "à l'inverse". 

5
Borja Bolilla
func Reverse(data Interface) Interface

Cela signifie qu'il faut un sort.Interface et renvoie un autre sort.Interface - il ne fait pas de tri lui-même. Par exemple, si vous passez sort.IntSlice (qui est essentiellement un []int qui peut être passé à sort.Sort pour le trier par ordre croissant), vous obtiendrez un nouveau sort.Interface qui triera les ints par ordre décroissant.

Soit dit en passant, si vous cliquez sur le nom de la fonction dans la documentation , il est directement lié à la source pour Reverse. Comme vous pouvez le constater, cela enveloppe simplement le sort.Interface que vous transmettez, de sorte que la valeur renvoyée par Reverse obtienne toutes les méthodes du sort.Interface d'origine. La seule méthode différente est la méthode Less qui retourne le contraire de la méthode Less sur le sort.Interface incorporé. Voir cette partie de la spécification de langue pour plus de détails sur les champs incorporés.

3
MatrixFrog

C’est une fonction inverse de tranche plus générique. Cela paniquera si l'entrée n'est pas une tranche.

//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)
    }
}
3
Yongke

Voici une autre façon de le faire

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

2
manugupt1

Voici une solution Go simple qui utilise une approche efficace (sans mémoire supplémentaire) pour inverser un tableau:

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

L'idée est que l'inversion d'un tableau équivaut à permuter chaque élément avec son image miroir au centre.

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

0
Pranjal Mittal

Pour inverser un tableau en place, parcourez-le jusqu'à son point milieu et échangez chaque élément avec son "élément miroir":

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

0
Martin Probst