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

Scala中NestedStrMap类嵌套Map构建及返回类型定义疑问

Scala中实现动态嵌套Map的NestedStrMap类

需求说明

我需要创建一个名为NestedStrMap的Scala类,类签名如下:

final class NestedStrMap[A](list: List[A], first: A => String, rest: (A => String)*)

要在这个类中实现asMap方法,利用first和可变参数rest中的函数,将输入的List[A]构建成嵌套的Map结构。但目前无法确定asMap的返回类型,初始实现因类型不匹配报错:

def asMap = {
  rest.toList.foldLeft(list.groupBy(first)) { (acc, i) =>
    acc.view.mapValues(l => l.groupBy(i)).toMap  // 类型不匹配报错
  }
}

期望效果

以下是目标使用示例,最终要得到多层嵌套的Map:

case class TestResult(name: String, testType: String, score: Int)

val testList = List(
  TestResult("A", "math", 75),
  TestResult("B", "math", 80),
  TestResult("B", "bio", 90),
  TestResult("C", "history", 50)
)
val nestedMap = NestedStrMap(testList, _.name, _.testType)
val someMap: Map[String, Map[String, List[TestResult]]] = nestedMap.asMap

println(someMap)
/*
输出:
Map(
  A -> Map(math -> List(TestResult(A,math,75))),
  B -> Map(math -> List(TestResult(B,math,80)), bio -> List(TestResult(B,bio,90))),
  C -> Map(history -> List(TestResult(C,history,50)))
)
*/

解决方案:可实现,利用递归类型推导

这个需求完全可以实现,核心是让编译器根据rest参数的数量,自动推导嵌套Map的类型。下面分别给出Scala 3和Scala 2的可行实现:

Scala 3 实现(推荐,利用匹配类型)

Scala 3的匹配类型(Match Types)可以直接定义递归的嵌套Map类型,代码简洁且类型推导自动完成:

final class NestedStrMap[A](private val list: List[A], first: A => String, rest: (A => String)*) {
  // 定义递归的嵌套Map类型:根据函数列表的长度决定嵌套层数
  private type NestedMap[Fs <: List[A => String]] = Fs match {
    case Nil => List[A]
    case _ :: tail => Map[String, NestedMap[tail]]
  }

  def asMap: NestedMap[first :: rest.toList] = {
    // 递归构建嵌套Map
    def build[Fs <: List[A => String]](currentList: List[A], fns: Fs): NestedMap[Fs] = fns match {
      case Nil => currentList
      case f :: remainingFns =>
        currentList.groupBy(f).view.mapValues { subList =>
          build(subList, remainingFns)
        }.toMap
    }

    build(list, first :: rest.toList)
  }
}

Scala 2 实现(利用隐式类型类)

Scala 2没有匹配类型,需要通过隐式类型类来递归推导嵌套类型:

import scala.language.implicitConversions

// 辅助类型类,用于推导嵌套Map类型
trait NestedMapBuilder[A] {
  type Out
  def build(list: List[A], fns: List[A => String]): Out
}

object NestedMapBuilder {
  // 基础情况:只有第一个函数时,返回Map[String, List[A]]
  implicit def base[A]: NestedMapBuilder[A] { type Out = Map[String, List[A]] } =
    new NestedMapBuilder[A] {
      type Out = Map[String, List[A]]
      def build(list: List[A], fns: List[A => String]): Out = list.groupBy(fns.head)
    }

  // 递归情况:每多一个函数,嵌套一层Map[String, ...]
  implicit def recursive[A, PrevOut](implicit prev: NestedMapBuilder[A] { type Out = PrevOut }): NestedMapBuilder[A] { type Out = Map[String, PrevOut] } =
    new NestedMapBuilder[A] {
      type Out = Map[String, PrevOut]
      def build(list: List[A], fns: List[A => String]): Out =
        prev.build(list, fns.tail).view.mapValues(_.groupBy(fns.head)).toMap
    }
}

final class NestedStrMap[A](private val list: List[A], first: A => String, rest: (A => String)*) {
  def asMap(implicit builder: NestedMapBuilder[A]): builder.Out = {
    builder.build(list, first :: rest.toList)
  }
}

使用时,编译器会自动推导asMap的返回类型,完全符合预期效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:25:00