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.
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.
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.)
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 int
s mais tombe en panne sur 10 millions.
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.
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".
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.
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)
}
}
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)
}
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.
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)
}