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

Scala实现为重复字符串添加重复次数后缀并保持顺序

Scala风格实现重复元素添加计数后缀

需求很明确:给定一个String类型的List,生成新List,其中重复出现的元素(区分大小写)会在后面添加.加上重复次数作为后缀,第一个出现的元素保持原样,同时严格保留原列表的顺序。比如输入List("a","a","a","b","b","c","C"),要输出List("a","a.1","a.2","b","b.1","c","C")。

用Scala的foldLeft可以很优雅地实现这个需求,它能在遍历过程中携带状态(这里就是每个元素的出现次数),完全替代传统的循环+计数Map的写法:

val input = List("a","a","a","b","b","c","C")

val result = input.foldLeft((scala.collection.mutable.ListBuffer[String](), Map.empty[String, Int])) {
  case ((buffer, countMap), elem) =>
    val currentCount = countMap.getOrElse(elem, 0)
    if (currentCount == 0) {
      buffer += elem
      (buffer, countMap + (elem -> 1))
    } else {
      buffer += s"$elem.$currentCount"
      (buffer, countMap + (elem -> (currentCount + 1)))
    }
}._1.toList

// 输出结果: List("a", "a.1", "a.2", "b", "b.1", "c", "C")

代码说明

  • foldLeft的初始状态:用一个元组保存两个值,一个是用来动态添加结果的ListBuffer(比List更适合频繁追加操作),另一个是记录每个元素出现次数的Map,初始为空。
  • 遍历逻辑:
    1. 对每个元素,先从计数Map里拿到它当前的出现次数,默认是0(第一次出现)。
    2. 如果是第一次出现,直接把元素加入结果缓冲区,同时更新Map中该元素的计数为1。
    3. 如果不是第一次出现,就生成带后缀的字符串加入缓冲区,然后把Map中该元素的计数加1。
  • 最终转换:把ListBuffer转成不可变的List,符合Scala的惯用风格。

如果想全程用不可变集合(避免使用ListBuffer),也可以把结果改成不可变List,但频繁追加的话性能会稍差一点,写法如下:

val input = List("a","a","a","b","b","c","C")

val result = input.foldLeft((List.empty[String], Map.empty[String, Int])) {
  case ((resList, countMap), elem) =>
    val currentCount = countMap.getOrElse(elem, 0)
    val newElem = if (currentCount == 0) elem else s"$elem.$currentCount"
    (resList :+ newElem, countMap + (elem -> (currentCount + 1)))
}._1

这个版本完全用不可变结构,更符合函数式编程的纯粹性,但因为List的:+操作是O(n)的,数据量大的时候推荐用第一个版本的ListBuffer。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:00:00