Scala映射约简与聚合
我有一个像这样的映射,类型为Map[String,Seq[String]]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(
"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:你介意看看这里类似的问题吗?