Dado este bloque de código
map[string]int {"hello":10, "foo":20, "bar":20}
Me gustaria imprimir
foo, 20
bar, 20
hello, 10
En el orden de mayor a menor
¡Gracias!
Respuestas:
Encontré la respuesta en Golang-nuts por Andrew Gerrand
Puede implementar la interfaz de clasificación escribiendo las funciones len / less / swap
func rankByWordCount(wordFrequencies map[string]int) PairList{
pl := make(PairList, len(wordFrequencies))
i := 0
for k, v := range wordFrequencies {
pl[i] = Pair{k, v}
i++
}
sort.Sort(sort.Reverse(pl))
return pl
}
type Pair struct {
Key string
Value int
}
type PairList []Pair
func (p PairList) Len() int { return len(p) }
func (p PairList) Less(i, j int) bool { return p[i].Value < p[j].Value }
func (p PairList) Swap(i, j int){ p[i], p[j] = p[j], p[i] }
Para ver la publicación original, encuéntrela aquí https://groups.google.com/forum/#!topic/golang-nuts/FT7cjmcL7gw
sort.Reverse
. +1.
Hay una nueva función sort.Slice en go 1.8, así que ahora esto es más simple.
package main
import (
"fmt"
"sort"
)
func main() {
m := map[string]int{
"something": 10,
"yo": 20,
"blah": 20,
}
type kv struct {
Key string
Value int
}
var ss []kv
for k, v := range m {
ss = append(ss, kv{k, v})
}
sort.Slice(ss, func(i, j int) bool {
return ss[i].Value > ss[j].Value
})
for _, kv := range ss {
fmt.Printf("%s, %d\n", kv.Key, kv.Value)
}
}
Por ejemplo:
package main
import (
"fmt"
"sort"
)
func main() {
m := map[string]int{"hello": 10, "foo": 20, "bar": 20}
n := map[int][]string{}
var a []int
for k, v := range m {
n[v] = append(n[v], k)
}
for k := range n {
a = append(a, k)
}
sort.Sort(sort.Reverse(sort.IntSlice(a)))
for _, k := range a {
for _, s := range n[k] {
fmt.Printf("%s, %d\n", s, k)
}
}
}
Salida:
foo, 20
bar, 20
hello, 10
A menudo necesito ordenar map[string]int
algo que estoy contando y he estado usando lo siguiente.
func rankMapStringInt(values map[string]int) []string {
type kv struct {
Key string
Value int
}
var ss []kv
for k, v := range values {
ss = append(ss, kv{k, v})
}
sort.Slice(ss, func(i, j int) bool {
return ss[i].Value > ss[j].Value
})
ranked := make([]string, len(values))
for i, kv := range ss {
ranked[i] = kv.Key
}
return ranked
}
Úselo para iterar sobre las claves en orden de valor
values := map[string]int{"foo": 10, "bar": 20, "baz": 1}
for i, index := range rankMapStringInt(values) {
fmt.Printf("%3d: %s -> %d", i, index, values[index])
}
En mi caso, estaba tratando con un programa que creé. En este programa, creé un mapa como tú, con string
y int
. Luego descubrí, como tú, que Go no tiene una forma incorporada de ordenar algo como esto. Leí las otras respuestas y realmente no me gustó lo que leí.
Así que intenté pensar en el problema de otra manera. Go puede usar sort.Ints
con una rebanada. Además, Go puede usar sort.Slice con un comparador personalizado. Entonces, en lugar de crear un mapa de string
y int
, creé un mapa struct
de
string
y int
. Entonces puedes ordenar:
package main
import (
"fmt"
"sort"
)
type File struct {
Name string
Size int
}
func main() {
a := []File{{"april.txt", 9}, {"may.txt", 7}}
f := func (n, n1 int) bool {
return a[n].Size < a[n1].Size
}
sort.Slice(a, f)
fmt.Println(a)
}
Esto no funcionará para todos, porque tal vez se vea obligado a lidiar con un mapa creado por otra persona. Pero fue útil para mí. La buena parte es que, a diferencia de todas las otras respuestas, esta no usa bucles.
Ordene las claves primero por valor y luego itere el mapa:
package main
import (
"fmt"
"sort"
)
func main() {
counts := map[string]int{"hello": 10, "foo": 20, "bar": 20}
keys := make([]string, 0, len(counts))
for key := range counts {
keys = append(keys, key)
}
sort.Slice(keys, func(i, j int) bool { return counts[keys[i]] > counts[keys[j]] })
for _, key := range keys {
fmt.Printf("%s, %d\n", key, counts[key])
}
}
Less
está devolviendo el resultado incorrecto. Para ordenar al revés, use>
.