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

Scala 3中如何合并ADT枚举集合内同类型统计项?

Scala 3枚举ADTs合并同类型统计项方案

首先先把你的Stats枚举定义好(假设是数值型统计项,合并逻辑为求和):

enum Stats:
  case MaximumHealth(value: Int)
  case HealthRegen(value: Int)

要实现同类型统计项合并,核心就是按枚举case分组,忽略参数值,然后对每组内的实例做数值合并。

步骤1:按枚举case分组

Scala 3的枚举实例自带enumCase方法,它会返回该实例对应的枚举case单例对象——同一个case的所有实例,enumCase是完全相同的,刚好可以作为分组的key:

val stats = Array(Stats.MaximumHealth(20), Stats.MaximumHealth(10), Stats.HealthRegen(5))
// 按枚举case分组,得到Map[EnumCase, Array[Stats]]
val groupedStats = stats.groupBy(_.enumCase)

步骤2:合并每组内的统计项

接下来给每组写合并逻辑,用模式匹配处理不同case的求和:

先写一个通用的合并函数,处理同类型统计项的累加:

def mergeSameTypeStats(items: Iterable[Stats]): Stats = items match {
  // 从第一个元素开始,依次和后面的元素合并
  case head :: tail =>
    tail.foldLeft(head) { (acc, curr) =>
      (acc, curr) match {
        case (Stats.MaximumHealth(a), Stats.MaximumHealth(b)) => Stats.MaximumHealth(a + b)
        case (Stats.HealthRegen(a), Stats.HealthRegen(b)) => Stats.HealthRegen(a + b)
        case _ => throw new IllegalArgumentException("不能合并不同类型的统计项")
      }
    }
  case Nil => throw new IllegalArgumentException("没有可合并的统计项")
}

然后用这个函数处理每个分组,再转成数组:

val mergedStats = groupedStats.values.map(mergeSameTypeStats).toArray
// 输出:Array(MaximumHealth(30), HealthRegen(5))

更优雅的写法(给枚举加合并方法)

如果想让代码更内聚,可以给每个枚举case单独定义合并方法:

enum Stats:
  case MaximumHealth(value: Int) extends Stats:
    def merge(other: MaximumHealth): MaximumHealth = MaximumHealth(this.value + other.value)
  case HealthRegen(value: Int) extends Stats:
    def merge(other: HealthRegen): HealthRegen = HealthRegen(this.value + other.value)

然后分组合并时用reduce:

val mergedStats = groupedStats.values.map { items =>
  items.reduce { (a, b) =>
    (a, b) match {
      case (mh1: Stats.MaximumHealth, mh2: Stats.MaximumHealth) => mh1.merge(mh2)
      case (hr1: Stats.HealthRegen, hr2: Stats.HealthRegen) => hr1.merge(hr2)
      case _ => throw new IllegalArgumentException("类型不匹配")
    }
  }
}.toArray

注意点

  • 如果你不想用enumCase,也可以用_.productPrefix(返回枚举case的名称字符串,比如"MaximumHealth"),但enumCase是类型安全的,更推荐。
  • 合并逻辑可以根据需求调整,比如不是求和而是取最大值,只需要修改对应case的合并代码即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 08:50:10