Acabo de tener un problema en el que tenía una variedad de estructuras, por ejemplo
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)
}
Digamos que quieres ordenarlo Axis
. ¿Cómo haces eso?
(Nota: he visto http://golang.org/pkg/sort/ y parece funcionar, pero tengo que agregar unas 20 líneas solo para ordenarlas por una clave muy simple. Tengo un fondo de Python donde está tan simple como sorted(planets, key=lambda n: n.Axis)
: ¿hay algo similar simple en Go?)
Respuestas:
ACTUALIZACIÓN: Esta respuesta se refiere a versiones anteriores de
go
. Para Go 1.8 y versiones posteriores, consulte la respuesta de AndreKR a continuación .Si desea algo un poco menos detallado que el
sort
paquete de biblioteca estándar , puede usar elgithub.com/bradfitz/slice
paquete de terceros . Utiliza algunos trucos para generar los métodosLen
ySwap
necesarios para clasificar su porción, por lo que solo necesita proporcionar unLess
método.Con este paquete, puede realizar el ordenamiento con:
La
planets[:]
parte es necesaria para producir un corte que cubra su matriz. Si haceplanets
un corte en lugar de una matriz, puede omitir esa parte.fuente
A partir de Go 1.8 ahora puede usar sort.Slice para ordenar un segmento:
Normalmente no hay razón para usar una matriz en lugar de una división, pero en su ejemplo está utilizando una matriz, por lo que debe superponerla con una división (agregar
[:]
) para que funcione consort.Slice
:La clasificación cambia la matriz, por lo que si realmente lo desea, puede continuar utilizando la matriz en lugar del segmento después de la clasificación.
fuente
sort.Slice
Es un poco sorprendente. Laless
función solo toma índices, por lo que debe (en esta respuesta) usar unaplanets
matriz capturada por separado . Parece que no hay nada que obligue a que el segmento ordenado y laless
función estén operando en los mismos datos. Para que esto funcione, debe escribirplanets
tres veces (DRY).planets[:]
Es crucial. Pero no entiendo por qué. Funciona sin embargo.[:]
.A partir de Go 1.8, la respuesta de @ AndreKR es la mejor solución.
Puede implementar un tipo de colección que implementa la interfaz de clasificación .
Aquí hay un ejemplo de dos de estos tipos que le permiten ordenar por Eje o Nombre:
fuente
Puede, en lugar de aplicar el
Sort interface
sobre[]Planet
que poner en práctica en un tipo que contiene la colección y un cierre que va a hacer la comparación. Debe proporcionar la implementación para el cierre de comparación de cada propiedad.Creo que este método es mejor que implementar un tipo Ordenar para cada propiedad de la estructura.
Esta respuesta está casi arrancada de los documentos de clasificación, por lo que no puedo dar mucho crédito por ello
Cómo llamarlo
Aquí hay una demostración
fuente
Aquí hay otra forma de reducir parte de la placa de la caldera. Descargo de responsabilidad, utiliza reflexiones y pérdidas tipo seguridad.
Aquí hay una demostración
Toda la magia sucede en la
Prop
función. Toma la propiedad de estructura para ordenar y el orden que desea ordenar (ascendente, descendente) y devuelve una función que realizará las comparaciones.fuente