如何根据索引在 Golang 中的映射中打印每个元素字符串及其频率?

huangapple go评论114阅读模式
英文:

How to print each elements string with its frequency based on index in map - Golang

问题

假设我有一个输入字符串和输出字符串,其中输出字符串将是字符串中每个元素的频率和字符本身。

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

在找到不同字符的频率后,我该如何按索引打印它们?

这是我的代码:

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)
	}

	// 不知道接下来该怎么做

}

代码的输出是:
output: n1p1r2o1g2a1m2i1

英文:

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

</details>


# 答案1
**得分**: 2

@icza的答案很好。这是我之前考虑过但直到现在才写出来的另一种方法。

它使用一个字符串来跟踪符文的顺序,但如果速度很重要,你可以使用字符串构建器。

```go
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)
	}
}
英文:

@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 := &quot;&quot;

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

	for _, c := range sOut {
		if sMap[c] &gt; 1 {
			fmt.Print(sMap[c])
		}
		fmt.Printf(&quot;%c&quot;, c)
	}
}

答案2

得分: 1

你正在计算rune的数量,所以可以使用map[rune]int的映射,这样你就可以省略转换回string的步骤。

映射是无序的,所以如果你希望输出的顺序与输入相同,就不能(也不应该)遍历映射。

一旦你统计了字母的数量,再次遍历_input_中的字母,并从映射中获取频率并删除它。如果计数大于1,还要打印数字。

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 // 字符已经打印并删除
        }
        delete(sMap, v)
        if count > 1 {
            fmt.Print(count)
        }
        fmt.Print(string(v))
    }
}

测试一下:

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

这将输出(在Go Playground上尝试一下):

In: programming
Out: p2ro2ga2min
In: ab
Out: ab
In: aba
Out: 2ab
In: aabcdeac
Out: 3ab2cde
英文:

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 &gt; 1 {
			fmt.Print(count)
		}
		fmt.Print(string(v))
	}
}

Testing it:

for _, s := range []string{&quot;programming&quot;, &quot;ab&quot;, &quot;aba&quot;, &quot;aabcdeac&quot;} {
	fmt.Println(&quot;In:&quot;, s)
	fmt.Print(&quot;Out: &quot;)
	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

huangapple
  • 本文由 发表于 2022年7月6日 13:24:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/72878302.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定