Traverse a Map in decreasing order of values

Issue

I’m trying to traverse a map in decreasing order of the values stored against keys. I’ve tried:

func frequencySort(s string) string {
  var frequency map[string]int
  chararray := strings.Split(s , "")
  var a []int
  var arranged map[int]string
  for k , v := range frequency {
      arranged[v] = k
  }
  for k := range arranged {
      a = append(a , k)
  }
  sort.Sort(sort.Reverse(sort.IntSlice{a}))
}

Let’s say the Map structure is :

    "a" : 9
    "b" : 7
    "c" : 19
    "d" : 11

and I’m trying to traverse it such that the output is :

"c" : 19
"d" : 11
"a" : 9
"b" : 7

Solution

The two map approach you have in your example will break as soon as you have more than one key in frequency with the same value, say "a":7 and "b":7, then you would lose data in arranged since keys have to be unique.

To avoid this you could create a helper type that will hold the map’s contents temporarily, just for sorting purposes. Something like this:

package main

import (
    "fmt"
    "sort"
)

var m = map[string]int{
    "a": 9,
    "b": 7,
    "c": 19,
    "d": 11,
}

type entry  struct {
    val int
    key string
}

type entries []entry

func (s entries) Len() int { return len(s) }
func (s entries) Less(i, j int) bool { return s[i].val < s[j].val }
func (s entries) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func main() {
    var es entries
    for k, v := range m {
        es = append(es, entry{val: v, key: k})
    }

    sort.Sort(sort.Reverse(es))

    for _, e := range es {
        fmt.Printf("%q : %d\n", e.key, e.val)   
    }
}

https://play.golang.org/p/TPb0zNCtXO

Answered By – mkopriva

Answer Checked By – Senaida (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.