1

Let say I have input and output string where the output will be the frequency of each elements in the string and the char itself

input := "programming"
output := "p2ro2ga2min"

How can I print it based on index after I found the freq of distinct character

This is my code

func countFreq(s string)  {
    sMap := make(map[string]int)

    for _, v := range s {
        sMap[string(v)]++
    }

    for i, v := range sMap {
        fmt.Printf("%v%v", i, v)
    }

    // Don't know what to do next

}

The output of code is 
output: n1p1r2o1g2a1m2i1
icza
  • 389,944
  • 63
  • 907
  • 827

2 Answers2

2

@icza's answer is great. Here's an alternative that I thought of before but only just got around to writing.

It uses a string to keep track of the rune order but you could use a string builder if speed is important.

func countFreq(s string) {
    sMap := make(map[rune]int)
    sOut := ""

    for _, c := range s {
        sMap[c]++
        if sMap[c] == 1 {
            sOut += string(c)
        }
    }

    for _, c := range sOut {
        if sMap[c] > 1 {
            fmt.Print(sMap[c])
        }
        fmt.Printf("%c", c)
    }
}
Andrew W. Phillips
  • 3,254
  • 1
  • 21
  • 24
  • Thank you so much for the answer and explanation. I need some time to understand how the code works since I am still trying to understand how the map works – adrian sitorus Jul 06 '22 at 08:57
1

You're counting runes, so use a map of map[rune]int, so you can omit the conversions back to string.

Maps are unordered, so if you want the output in the same order as the input, you can't (shouldn't) iterate over the map.

Once you counted the letters, range over the input letters again, and get the frequency from the map, and remove it. If the count is greater than 1, also print the number.

func countFreq(s string) {
    sMap := make(map[rune]int)

    for _, v := range s {
        sMap[v]++
    }

    for _, v := range s {
        count := sMap[v]
        if count == 0 {
            continue // Char already printed and removed
        }
        delete(sMap, v)
        if count > 1 {
            fmt.Print(count)
        }
        fmt.Print(string(v))
    }
}

Testing it:

for _, s := range []string{"programming", "ab", "aba", "aabcdeac"} {
    fmt.Println("In:", s)
    fmt.Print("Out: ")
    countFreq(s)
    fmt.Println()
}

This will output (try it on the Go Playground):

In: programming
Out: p2ro2ga2min
In: ab
Out: ab
In: aba
Out: 2ab
In: aabcdeac
Out: 3ab2cde
icza
  • 389,944
  • 63
  • 907
  • 827