Scala映射约简与聚合

Scala映射约简与聚合,scala,Scala,我有一个像这样的映射,类型为Map[String,Seq[String]] Map( "5" -> Seq("5.1"), "5.1" -> Seq("5.1.1", "5.1.2"), "5.1.1" -> Seq("5.1.1.1"), "5.1.2" -> Seq.empty[String], "5.1.1.1" -> Seq.empty[String] ) 给定一个键,我希望递归地获取属于给定键的所有值。例如,如果我想查找键5,我希望结果是: G

我有一个像这样的映射,类型为Map[String,Seq[String]]

Map(
 "5" -> Seq("5.1"),
 "5.1" -> Seq("5.1.1", "5.1.2"),
 "5.1.1" -> Seq("5.1.1.1"),
 "5.1.2" -> Seq.empty[String],
 "5.1.1.1" -> Seq.empty[String]
)
给定一个键,我希望递归地获取属于给定键的所有值。例如,如果我想查找键5,我希望结果是:

Given Input is: 5
Expected Output is: Seq(5.1, 5.1.1, 5.1.2, 5.1.1.1)
以下是我迄今为止所做的尝试:

def fetchSequence(inputId: String, acc: Seq[String], seqMap: Map[String, Seq[String]]): Seq[String] = seqMap.get(inputId) match {
  case None => acc
  case Some(subSeq) =>
    val newAcc = acc ++ subSeq
    subSeq.collect {
      case subId=> fetchSequence(subId, newAcc, seqMap)
    }.flatten
}

当我使用上面的映射调用fetchSequence时,得到一个空结果。

更简洁一些:

def recGet[A](map: Map[A, Seq[A]])(key: A): Seq[A] = 
  map.get(key).fold(
    // return empty Seq if key not found
    Seq.empty[A])(
    // return a Seq with 
    //   the key and 
    //   the result of recGet called recursively 
    //      (for all the elements in the Seq[A] found for key)
    x => Seq(key) ++ x.flatMap(recGet(map)))
您可以使用
recGet
作为:

val sections = Map(
  "5" -> Seq("5.1"),
  "5.1" -> Seq("5.1.1", "5.1.2"),
  "5.1.1" -> Seq("5.1.1.1"),
  "5.1.2" -> Seq.empty[String],
  "5.1.1.1" -> Seq.empty[String]
)

recGet(sections)("5")      // Seq[String] = List(5, 5.1, 5.1.1, 5.1.1.1, 5.1.2)
recGet(sections)("5.1.1")  // Seq[String] = List(5.1.1, 5.1.1.1)
recGet(sections)("5.2")    // Seq[String] = List()

这还将为您提供(第一个)元素本身(如果它存在于映射中),如果您不想这样做,您可以使用另一种方法包装
recGet
,该方法使用
drop(1)
recGet

的结果进行更简洁的处理:

def recGet[A](map: Map[A, Seq[A]])(key: A): Seq[A] = 
  map.get(key).fold(
    // return empty Seq if key not found
    Seq.empty[A])(
    // return a Seq with 
    //   the key and 
    //   the result of recGet called recursively 
    //      (for all the elements in the Seq[A] found for key)
    x => Seq(key) ++ x.flatMap(recGet(map)))
您可以使用
recGet
作为:

val sections = Map(
  "5" -> Seq("5.1"),
  "5.1" -> Seq("5.1.1", "5.1.2"),
  "5.1.1" -> Seq("5.1.1.1"),
  "5.1.2" -> Seq.empty[String],
  "5.1.1.1" -> Seq.empty[String]
)

recGet(sections)("5")      // Seq[String] = List(5, 5.1, 5.1.1, 5.1.1.1, 5.1.2)
recGet(sections)("5.1.1")  // Seq[String] = List(5.1.1, 5.1.1.1)
recGet(sections)("5.2")    // Seq[String] = List()

这还将为您提供(第一个)元素本身(如果它存在于地图中),如果您不想这样做,您可能可以使用另一种方法包装
recGet
,该方法使用
drop(1)
recGet

的结果进行处理,这太棒了!我猜它会在递归键上无限循环(例如
“5”->Seq(“5.1”,“5”)
)?@evan058确实,如果是这样的话,你需要能够检查当前的“结果”,这在像这样的递归键上是不可能的。酷!我想我不会遇到像“5”->Seq(“5.1”,“5”)@Peter:你介意看看这里类似的问题吗?这太棒了!我猜它会在递归键上无限循环(例如
“5”->Seq(“5.1”,“5”)
)?@evan058确实,如果是这样的话,你需要能够检查当前的“结果”,这在像这样的递归键上是不可能的。酷!我想我不会遇到像“5”->Seq(“5.1”,“5”)@Peter:你介意看看这里类似的问题吗?