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

Scala集合:遍历列表时如何携带状态处理重复元素?

解决Scala中带状态修改列表重复元素的问题

嘿,这个需求我太熟了!确实map方法完全满足不了,因为它是无状态的——每处理一个元素时,根本没法记住之前已经出现过多少次相同的元素。要实现给重复元素加序号的效果,我们得用带状态的遍历方法,比如foldLeft,它能帮我们在遍历过程中维护一个累加器来跟踪状态。

需求回顾

输入列表:

val l1 = List("a","b","c","d","e","f","b","c","e","b","a")

期望输出:
List(a1, b1, c1, d, e1, f, b2, c2, e2, b3, a2)
规则:只有出现次数大于1的元素,每次出现都加上当前的出现序号;仅出现一次的元素保留原样。

解决方案代码

// 第一步:先统计每个元素的总出现次数,用来判断是否需要加序号
val l1 = List("a","b","c","d","e","f","b","c","e","b","a")
val elementTotalCounts = l1.groupBy(identity).view.mapValues(_.size).toMap

// 第二步:用foldLeft维护状态遍历列表
val (finalResult, _) = l1.foldLeft((List.empty[String], Map.empty[String, Int])) { 
  case ((resultAccumulator, currentCountMap), elem) =>
    // 获取当前元素已经出现的次数,加1得到本次的序号
    val currentOccurrence = currentCountMap.getOrElse(elem, 0) + 1
    // 判断是否需要加序号:总次数>1则拼接,否则保留原元素
    val modifiedElem = if (elementTotalCounts(elem) > 1) s"$elem$currentOccurrence" else elem
    // 更新累加器:把新元素加入结果列表,更新计数Map
    (resultAccumulator :+ modifiedElem, currentCountMap + (elem -> currentOccurrence))
}

// 输出结果就是你想要的
println(finalResult)
// 输出:List(a1, b1, c1, d, e1, f, b2, c2, e2, b3, a2)

代码解释

  1. elementTotalCounts:通过groupBy把相同元素分组,再统计每组的大小,得到每个元素的总出现次数。这一步是为了区分“需要加序号的元素”和“不需要加序号的元素”(比如d、f只出现一次,就不用加)。
  2. foldLeft的累加器:我们用一个元组(List[String], Map[String, Int])作为累加器,前者存处理后的结果,后者存每个元素当前已经出现的次数。
  3. 每次遍历的逻辑:
    • 先计算当前元素这次是第几次出现;
    • 根据总出现次数判断是否要加序号;
    • 更新结果列表和计数Map,继续下一次遍历。

这种方法的优势是只需要遍历列表两次(一次统计次数,一次处理元素),效率很高,而且逻辑清晰,完全满足带状态修改的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:55:11