2017-05-31 5 views
0

Ich stecke mit einem Problem fest. Also das Problem ist.Erstellen einer verschachtelten Clojure Map durch Aufruf der Funktion mit ihren Schlüsseln und Werten

  • Ich habe eine Karte wie diese {:first {"value1" "value2" "value3"...} :second {"value1" "value2" "value3"...}....}.
  • ich eine Funktion haben, die eine Anfrage an den Server mit den Parametern (first&value1) und zurück einige Informationen (es muss mit jedem Schlüssel machen Anfrage und ihre Werte (first&value1, first&value2 ...second&value1...))
  • Nächster Schritt ist es, neue Karte zu erzeugen, wie:

    {:first 
        {:value1 
        {subvalue1, subvalue2 ..} 
        :value2 
        {subvalue2-1,subvalue2-2}}  
    :second 
        {:value3 
        {:subvalue3-1,:subvalue3-2}..}..} 
    

Teilwerte ist das Ergebnis einer Anfrage mit jeder Taste und jedem Element seines Wertes zu machen. Und ich möchte die Operation noch einmal wiederholen (mit 3 Parametern, wenn ich eine Anfrage an den Server), um 4 mal verschachtelte Karte zu erreichen: {first {second {third {fourth}}}}. Vielleicht gibt mir jemand hilfreiche Ratschläge, wie es geht.

+0

Wenn der Wert von ': first' eine Reihe von Werten ist, wie es Ihre Daten andeuten, dann ist' ["value1" "value2" "value3"] 'sinnvoll, aber' {"value1" "value2" "value3" } macht keinen Sinn, da eine Karte eine gerade Anzahl von Formularen haben muss. –

+0

Könnten Sie bitte ein Beispiel für die tatsächlichen Daten und ihre erwartete Transformation hinzufügen? Die Frage ist mit Fehlern rund um die Karten (ungerade Anzahl von Elementen) gespickt und Sie wollen entweder eine Liste oder einen Satz dort oder es ist nur verwirrend. Bitte fügen Sie auch das hinzu, was Sie bisher selbst versucht haben, um es uns leichter zu machen, das zu erfassen. – cfrick

+0

Tut mir leid, ich habe das Problem nicht richtig erklärt. Die letzte verschachtelte Map sollte einen Vektor oder eine Sequenz als Wert haben {: viertel ["value1" "value2"] ....} –

Antwort

2

Diese Funktion ist ein bisschen langatmig, aber das tut, was Sie es tun müssen, um:

(defn rec-update 
    [m f] 
    (let [g (fn g [m args] 
      (into {} 
        (for [[k v] m] 
        (if (instance? java.util.Map v) 
         [k (g v (conj args (name k)))] 
         [k (into {} (map #(let [args (into args [(name k) (name %)])] 
              [(keyword %) (f args)]) 
             v))]))))] 
    (g m []))) 

Der f Parameter sollte eine Funktion sein, die eine Sammlung von params nimmt, und gibt einen Vektor der Ergebnisse. Hier ist ein Beispiel, das Zufallszahlen von Zufallsantworten nimmt:

(defn make-request 
    [params] 
    (vec (repeatedly (+ 1 (rand-int 3)) #(rand-nth ["r1" "r2" "r3"])))) 

Obwohl das folgende Beispiel nicht zeigen, die params diese Funktion gegeben wird in der Tat die verschachtelten Werte bis zu diesem Punkt.

benutzen:

(def m {:first ["val1" "val2" "val3"], :second ["val4" "val5"]}) 

(rec-update m make-request) 
=> 
{:first {:val1 ["r2" "r2" "r3"], :val2 ["r2" "r2"], :val3 ["r1" "r3"]}, 
:second {:val4 ["r3" "r3"], :val5 ["r2" "r1"]}} 

Run wieder auf das Ergebnis:

(rec-update *1 make-request) 
=> 
{:first {:val1 {:r2 ["r1" "r3" "r2"], :r3 ["r3" "r2"]}, 
     :val2 {:r2 ["r1" "r1"]}, 
     :val3 {:r1 ["r2"], :r3 ["r1" "r2" "r3"]}}, 
:second {:val4 {:r3 ["r3" "r2"]}, :val5 {:r2 ["r1"], :r1 ["r2" "r3"]}}} 

Wie Sie sehen können, alle doppelten Werte aus der Anforderung nur einmal in der Ergebnis Karte dargestellt werden zurückgegeben wird.

+0

Vielen Dank, Josh, aber ich habe noch eine Frage. Ich denke, ich habe die Idee nicht richtig erklärt (sorry dafür). Meine Funktion f macht eine Anfrage an den Server und die Anfrage aussehen likes (http: // website/information/get_information? Param1 = erste & param2 = wert1 & param3 = subvalue1? Param4 = subsubvalue1 es wird eine vollständige Anfrage ich will und es sollte eine one " Zweig "meiner verschachtelten Karte). Also im ersten Schritt, machen Sie einfach eine Anfrage mit 1 Parameter (zuerst) und rufen Sie alle damit verbundenen Informationen ab. Zweitens mache ich ein reqst mit 2 params (first und value1) und so weiter. –

+0

So jetzt habe ich erste Ebene meiner zukünftigen Karte {: erste ("value1" "value2"): zweite ("value1" "value2") ....} –

+0

Der obige Code funktioniert für dieses Szenario @AndreiBelkevich - die Funktion 'f', die Sie zu' rec-update' geben, sollte ein Argument erwarten, das ein Vektor sein wird, der stringifizierte Schlüsselwörter aus Ihrer Map enthält. Sie müssen 'f' schreiben, wo Sie Ihre Anfrage stellen und einen Vektor von Antworten zurückgeben. Schreiben Sie eine Testfunktion, die ihr Argument ausgibt und es in 'rec-update' übergibt und Sie werden sehen, was ich meine. – Josh

Verwandte Themen