Jeśli, tak jak ja, okaże się, że potrzebujesz zasadniczo tego samego kodu sortowania w więcej niż jednym miejscu lub po prostu chcesz zachować złożoność kodu, możesz przenieść samo sortowanie do oddzielnej funkcji, do której przekazujesz funkcję, która to robi rzeczywistą pracę, jaką chcesz (która będzie oczywiście inna w każdym miejscu telefonicznym).
Biorąc pod uwagę, mapa z kluczem typu K
i rodzaju wartości V
, reprezentowane <K>
i <V>
poniżej, wspólna funkcja sortowania może wyglądać ten szablon Go-kodu (który Go w wersji 1 nie obsługuje jak jest):
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)
}
}
Następnie wywołaj go z mapą wejściową i funkcją (przyjmującą (k <K>, v <V>)
jako argumenty wejściowe), która jest wywoływana nad elementami mapy w kolejności posortowanych kluczy.
Tak więc wersja kodu w odpowiedzi opublikowanej przez Mingu może wyglądać następująco:
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() {
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) })
}
sortedMapIntString()
Funkcja może być ponownie wykorzystane dla każdego map[int]string
(zakładając, że pożądany jest taki sam porządek), utrzymując każdym użyciu tylko dwóch przewodów kodu.
Wady obejmują:
- Trudniej go czytać osobom nieprzyzwyczajonym do używania funkcji jako pierwszorzędnych
- Może być wolniejszy (nie robiłem porównań wydajności)
Inne języki mają różne rozwiązania:
- Jeśli użycie
<K>
and <V>
(do oznaczania typów dla klucza i wartości) wygląda trochę znajomo, ten szablon kodu nie różni się zbytnio od szablonów C ++.
- Clojure i inne języki obsługują posortowane mapy jako podstawowe typy danych.
- Chociaż nie wiem w żaden sposób, w jaki sposób Go tworzy
range
typ pierwszej klasy, tak aby można go było zastąpić niestandardowym ordered-range
(zamiast range
w oryginalnym kodzie), myślę, że niektóre inne języki zapewniają iteratory, które są wystarczająco potężne, aby osiągnąć to samo rzecz.