2016-06-29 6 views
1

Ich habe eine Karte, die so aussieht und ist vom Typ Map [String, Seq [Zeichenfolge]]Scala Map Reduktion und Aggregation

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] 
) 

einen Schlüssel, ich möchte alle Werte holen rekursiv, dass gehört zu dem angegebenen Schlüssel. Sagen Sie zum Beispiel, wenn ich für den Schlüssel 5 nachschlagen möchten, erwarte ich das Ergebnis sein.

Given Input is: 5 
Expected Output is: Seq(5.1, 5.1.1, 5.1.2, 5.1.1.1) 

Hier ist, was ich bisher versucht:

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 
} 

ich ein leeres Ergebnis erhalten wenn ich fetchSequence mit der Map anrufe, die ich oben habe.

Antwort

4

Etwas knapper:

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))) 

Sie können recGet als:

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() 

Dies wird Ihnen auch das (erste) Element selbst (wenn es in der Karte vorhanden ist), wenn Sie das wollen Sie nicht, Sie können wahrscheinlich in einer anderen Methode wrappen, die drop(1) auf das Ergebnis recGet verwendet.

+1

Das ist fantastisch! Ich schätze, es würde endlos auf rekursive Tasten (zB "5" -> Seq ("5.1", "5")) "? –

+0

@ evan058 In der Tat, wenn das der Fall ist, müssen Sie in der Lage sein, das aktuelle "Ergebnis" zu inspizieren, was bei etwas Rekursivem wie diesem unmöglich ist. –

+0

Cool! Ich denke, ich werde keine Situationen haben, in denen ich Tasten wie "5" -> Seq ("5.1", "5") habe. – sparkr