Si, como yo, descubre que desea esencialmente el mismo código de clasificación en más de un lugar, o simplemente desea mantener baja la complejidad del código, puede abstraer la clasificación en una función separada, a la que le pasa la función que hace el trabajo real que desea (que sería diferente en cada sitio de llamada, por supuesto).
Dado un mapa con el tipo de clave K
y el tipo de valor V
, representado como <K>
y a <V>
continuación, la función de clasificación común podría parecerse a esta plantilla de código Go (que la versión 1 de Go no admite tal como está):
/* Go apparently doesn't support/allow 'interface{}' as the value (or
/* key) of a map such that any arbitrary type can be substituted at
/* run time, so several of these nearly-identical functions might be
/* needed for different key/value type combinations. */
func sortedMap<K><T>(m map[<K>]<V>, f func(k <K>, v <V>)) {
var keys []<K>
for k, _ := range m {
keys = append(keys, k)
}
sort.Strings(keys) # or sort.Ints(keys), sort.Sort(...), etc., per <K>
for _, k := range keys {
v := m[k]
f(k, v)
}
}
Luego llámelo con el mapa de entrada y una función (tomando (k <K>, v <V>)
como argumentos de entrada) que se invoca sobre los elementos del mapa en orden de clave ordenada.
Entonces, una versión del código en la respuesta publicada por Mingu podría verse así:
package main
import (
"fmt"
"sort"
)
func sortedMapIntString(m map[int]string, f func(k int, v string)) {
var keys []int
for k, _ := range m {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
f(k, m[k])
}
}
func main() {
// Create a map for processing
m := make(map[int]string)
m[1] = "a"
m[2] = "c"
m[0] = "b"
sortedMapIntString(m,
func(k int, v string) { fmt.Println("Key:", k, "Value:", v) })
}
La sortedMapIntString()
función se puede reutilizar para cualquier map[int]string
(suponiendo que se desee el mismo orden de clasificación), manteniendo cada uso en solo dos líneas de código.
Las desventajas incluyen:
- Es más difícil de leer para las personas que no están acostumbradas a usar funciones como de primera clase.
- Puede que sea más lento (no he hecho comparaciones de rendimiento)
Otros idiomas tienen varias soluciones:
- Si el uso de
<K>
y <V>
(para denotar tipos para la clave y el valor) parece un poco familiar, esa plantilla de código no es muy diferente a las plantillas de C ++.
- Clojure y otros lenguajes admiten mapas ordenados como tipos de datos fundamentales.
- Si bien no conozco ninguna forma en que Go haga
range
un tipo de primera clase que pueda ser sustituido por uno personalizado ordered-range
(en lugar del range
código original), creo que algunos otros lenguajes proporcionan iteradores que son lo suficientemente potentes para lograr lo mismo cosa.