Ich hatte gerade ein Problem, bei dem ich eine Reihe von Strukturen hatte, z
package main
import "log"
type Planet struct {
Name string `json:"name"`
Aphelion float64 `json:"aphelion"` // in million km
Perihelion float64 `json:"perihelion"` // in million km
Axis int64 `json:"Axis"` // in km
Radius float64 `json:"radius"`
}
func main() {
var mars = new(Planet)
mars.Name = "Mars"
mars.Aphelion = 249.2
mars.Perihelion = 206.7
mars.Axis = 227939100
mars.Radius = 3389.5
var earth = new(Planet)
earth.Name = "Earth"
earth.Aphelion = 151.930
earth.Perihelion = 147.095
earth.Axis = 149598261
earth.Radius = 6371.0
var venus = new(Planet)
venus.Name = "Venus"
venus.Aphelion = 108.939
venus.Perihelion = 107.477
venus.Axis = 108208000
venus.Radius = 6051.8
planets := [...]Planet{*mars, *venus, *earth}
log.Println(planets)
}
Nehmen wir an, Sie möchten es sortieren Axis
. Wie machst du das?
(Hinweis: Ich habe http://golang.org/pkg/sort/ gesehen und es scheint zu funktionieren, aber ich muss ungefähr 20 Zeilen hinzufügen, nur um sie einfach nach einem sehr einfachen Schlüssel zu sortieren. Ich habe dort einen Python-Hintergrund so einfach wie sorted(planets, key=lambda n: n.Axis)
- gibt es etwas ähnlich Einfaches in Go?)
Antworten:
UPDATE: Diese Antwort bezieht sich auf ältere Versionen von
go
. Informationen zu Go 1.8 und neuer finden Sie in der Antwort des AndreKR unten .Wenn Sie etwas weniger Ausführliches als das Standardbibliothekspaket wünschen
sort
, können Sie dasgithub.com/bradfitz/slice
Paket eines Drittanbieters verwenden . Es werden einige Tricks verwendet, um dieLen
undSwap
Methoden zu generieren, die zum Sortieren Ihres Slice erforderlich sind. Sie müssen also nur eineLess
Methode angeben.Mit diesem Paket können Sie die Sortierung durchführen mit:
Das
planets[:]
Teil ist erforderlich, um ein Slice zu erstellen, das Ihr Array abdeckt. Wenn Sieplanets
anstelle eines Arrays ein Slice erstellen, können Sie diesen Teil überspringen.quelle
Ab Go 1.8 können Sie jetzt sort.Slice verwenden , um ein Slice zu sortieren:
Normalerweise gibt es keinen Grund, ein Array anstelle eines Slice zu verwenden. In Ihrem Beispiel verwenden Sie jedoch ein Array. Sie müssen es daher mit einem Slice (Add
[:]
) überlagern , damit es funktioniertsort.Slice
:Die Sortierung ändert das Array. Wenn Sie also wirklich möchten, können Sie das Array nach dem Sortieren anstelle des Slice weiter verwenden.
quelle
sort.Slice
ist irgendwie überraschend. Dieless
Funktion akzeptiert nur Indizes und muss (in dieser Antwort) ein separat erfasstesplanets
Array verwenden. Es scheint nichts zu geben, was erzwingt, dass das sortierte Slice und dieless
Funktion mit denselben Daten arbeiten. Damit dies funktioniert, müssen Sieplanets
dreimal (DRY) eingeben.planets[:]
ist entscheidend. Aber ich verstehe nicht warum. Funktioniert aber.[:]
.Ab Go 1.8 ist die Antwort von @ AndreKR die bessere Lösung.
Sie können einen Sammlungstyp implementieren, der die Sortierschnittstelle implementiert .
Hier ist ein Beispiel für zwei solche Typen, mit denen Sie entweder nach Achse oder nach Name sortieren können:
quelle
Sie können das
Sort interface
On, das[]Planet
Sie implementieren, für einen Typ implementieren, der die Auflistung und einen Abschluss enthält, der den Vergleich durchführt. Sie müssen die Implementierung für den Vergleichsabschluss für jede Eigenschaft bereitstellen.Diese Methode ist meiner Meinung nach besser als die Implementierung eines Sortiertyps für jede Eigenschaft der Struktur.
Diese Antwort ist fast direkt aus den Sortierdokumenten herausgerissen, so dass ich nicht viel Anerkennung dafür finden kann
Wie man es nennt.
Hier ist eine Demo
quelle
Hier ist eine andere Möglichkeit, einen Teil der Kesselplatte zu reduzieren. Haftungsausschluss, es verwendet Reflexion und Verluste Typ Sicherheit.
Hier ist eine Demo
Die ganze Magie geschieht in der
Prop
Funktion. Es nimmt die struct-Eigenschaft zum Sortieren und die Reihenfolge, nach der Sie sortieren möchten (aufsteigend, absteigend), und gibt eine Funktion zurück, die die Vergleiche ausführt.quelle