Scala:圈复杂度对于模式匹配案例类来说太高了

问题描述

我有几个案例类,例如:

case class TypeX(a: Int,b: Int,c: String)
sealed trait metrictypes
object metrictypes {
  case class SuccessCount(a: TypeX) extends metrictypes
  case class FailureCount(a: TypeX) extends metrictypes
  case class WarningCount(a: TypeX) extends metrictypes
     .....

我有 10 个这样的案例类 ^

我有一些功能可以生成 List[metrictypes] 类型的列表 collectedList。例如:

List(SuccessCount(TypeX(111,222,"abc")),WarningCount(TypeX(999,777,"zzz")))

我需要计算 metrictype 并在列表 finalList 中收集 TypeX。我正在做类似的事情:

  val finalList = new ListBuffer[TypeX]()
  val result = collectedList {x =>
    x match {
      case SuccessCount(a)  => incrementSuccessCount(); finalList += a
      case FailureCount(a)  => incrementFailureCount(); finalList += a
      .... (10 times)
      case _ => println("Unknown!")

    }
  }

我知道这不是最干净或最有效的方法,而且还会导致高圈复杂度。我该如何改进?

我还尝试通过以下方式根据度量类型对它们进行分组:

  val groupedList = collectedList.groupBy(i => i).mapValues(_.map(_ => 1).reduce(_ + _))

结果是

Map(SuccessCount(TypeX(111,"abc")) -> 1,"zzz")) -> 1))

仍然无法弄清楚如何获取 metrictypes 的出现次数并仅在列表中收集 TypeX。

解决方法

如果您将设计稍微更改为这样的内容会怎样:

final case class TypeX(a: Int,b: Int,c: String)

sealed trait MetricType
object MetricType {
  final case object Success extends MetricType
  final case object Failure extends MetricType
  final case object Warning extends MetricType
}

final case class MetricCount(tpe: MetricType,a: TypeX)

然后你可以这样使用:

def processCounts(data: List[MetricCount]): (List[TypeX],Map[MetricType,Int]) = {
  val finalList = data.map(_.a)
  val countsByMetricType = data.groupMapReduce(_.tpe)(_ => 1)(_ + _)
  
  finalList -> countsByMetricType
}

这有帮助吗?

,

如果您的案例类中的所有数据实际上都有 TypeX 的数据,那么您应该使用 metrictype 特征来概括您的所有案例类都有一个 a: TypeX,那么您只需map您的collectedLista,而不必对所有内容进行模式匹配。

另一方面,在您的列表中收集特定类型的数据。 因为我们希望能够根据类型而不是数据进行收集。 你最好在你的 collect 上做一个 collectedList 并对你正在追逐的类型进行部分匹配 ala

val successList = collectedList.collect { case i: SuccessCount => i }
val warningList = collectedList.collect { case i: WarningCount => i }

您甚至可以通过为自己创建一个辅助函数来概括这一点:

def collectByType[B <: A](collectedList: List[A]): List[B] =
  collectedList.collect{ case i: B => i }
val successList = collectByType[SuccessCount](collectedList)
val warningList = collectByType[WarningCount](collectedList)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...