You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang统计字符频次后如何按原索引顺序输出结果

问题背景

需求规则:输入任意字符串,输出结果需遵循两个规则:

  1. 按字符在原字符串中首次出现的顺序拼接内容
  2. 每个字符仅在首次出现位置展示:字符本身 + 该字符在全串的总出现频次,若频次为1则省略频次数字
    示例:输入input := "programming"时,预期输出output := "p2ro2ga2min"。

现有实现问题:通过map存储字符计数值的逻辑是正确的,但Go语言中map遍历顺序是随机无序的,直接遍历map输出会完全打乱原字符串的字符顺序,当前代码输出为n1p1r2o1g2a1m2i1,不符合顺序要求,也未处理频次为1时省略数字的逻辑。

解决思路

核心是绕开map无序的特性,不要直接遍历map生成结果:

  • 第一步:保留原有map统计频次的逻辑,先遍历一次全串,拿到每个字符的总出现次数
  • 第二步:新增一个辅助集合,记录已经输出过的字符,避免同一个字符重复拼接频次
  • 第三步:直接遍历原始字符串(遍历顺序就是原索引顺序,完全匹配输出要求的顺序),遇到未输出过的字符时,拼接字符本身;如果该字符总频次大于1,再拼接对应的频次数字,之后把字符标记为已输出;遇到已经输出过的字符直接跳过即可。
修正后代码
package main

import (
	"fmt"
	"strings"
)

func buildResult(s string) string {
	// 统计每个字符的总出现频次
	freqMap := make(map[rune]int)
	for _, c := range s {
		freqMap[c]++
	}

	var builder strings.Builder
	// 记录已经完成输出的字符,避免重复拼接
	printed := make(map[rune]bool)

	// 按原字符串顺序遍历,而非遍历无序的map
	for _, c := range s {
		if printed[c] {
			continue
		}
		// 拼接字符本身
		builder.WriteRune(c)
		// 频次大于1才拼接数字,频次为1时省略
		if freqMap[c] > 1 {
			builder.WriteString(fmt.Sprintf("%d", freqMap[c]))
		}
		printed[c] = true
	}
	return builder.String()
}

func main() {
	input := "programming"
	output := buildResult(input)
	fmt.Println(output)
}
关键说明
  • 遍历原始字符串的顺序就是字符首次出现的索引顺序,从根源上解决了map无序导致的顺序错乱问题
  • 用strings.Builder做字符串拼接比直接用+拼接性能更好,尤其是字符串较长时优势明显
  • 辅助mapprinted的作用是去重,确保每个字符的频次只在第一次出现时输出一次,不会重复拼接
  • 代码中用rune类型处理字符,可以兼容中文等多字节字符,不会出现编码乱码问题

内容的提问来源于stack exchange,提问作者adrian sitorus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:24:20