2017-11-02 2 views
1

Ich habe eine Reihe von URLs, und einige der URLs haben indirekte Referenzen (als Vektor). Jede URL, die keine indirekte Referenz hat, hat nur nil. Ich fange mit dem folgenden Testkarte aus:Verschachtelte Vektoren aus der Karte in Clojure erstellen

{"URL 1" nil, 
"URL 2" ["indirect 1" "indirect 2"]} 

ich hiccup bin mit einem HTML-Bericht erstellen, so möchte ich diese Ausgabe:

[:div "Imports: " 
[:ul 
    [:li "URL 1"] 
    [:li "URL 2"] 
    [:ul 
    [:li "indirect 1"] 
    [:li "indirect 2"] 
    [:li "indirect 3"]]]] 

Ich bin in einige Probleme laufen Rückkehr Nil, wenn die URL keine indirekte Referenz hat. Meine aktuellen Code sieht wie folgt aus:

(defn list-imports 
    [imports] 
    (if-not (nil? imports) 
    [:div "Imports: " 
    [:ul 
     (for [direct (keys imports)] 
     [[:li direct] 
     (if-let [indirects (get imports direct)] 
      [:ul 
      (for [indirect indirects] 
       [:li indirect])] 
      [:span])])]] 
    [:div "Imports: none" [:br] [:br]])) 

Das Problem ist, es ist diese Rückkehr ...

[:div 
"Imports: " 
[:ul 
    ([[:li "URL 1"] [:span]] 
    [[:li "URL 2"] [:ul ([:li "indirect 1"] [:li "indirect 2"])]])]] 

ich in einem [:span] Tag wie der Fall fügen musste für, wenn die indirekten Importe nil, was ich da eigentlich nicht will ... aber sonst steckt es dort in nil.

Das andere Problem ist, dass es endet in () und einen zusätzlichen Vektor eingeschlossen, weil ich mehrere Dinge innerhalb der for-Anweisung mache. Wenn ich versuche, es mit Schluckauf zu konvertieren, bekomme ich [:li "URL 1"] is not a valid element name.

Antwort

1

Dies kann ein kniffliger Aspekt der Erstellung von Schluckauf-Tags sein. Manchmal hilft es, das Problem in kleinere Stücke zu zerlegen.

(defn list-indirects 
    [indirects] 
    (when (seq indirects) 
    [(into [:ul] (mapv (fn [i] [:li i]) indirects))])) 

(defn list-imports 
    [imports] 
    (if (some? imports) 
    [:div "Imports: " 
    (into [:ul] 
     (for [[url indirects] imports] 
     (into [:li url] (list-indirects indirects))))] 
    [:div "Imports: none" [:br] [:br]])) 

Diese Funktionen sollten Ihnen die gewünschte Ausgabe geben.

(list-imports {"URL 1" nil 
       "URL 2" ["indirect 1" "indirect 2"]}) 
=> 
[:div "Imports: " 
[:ul 
    [:li "URL 1"] 
    [:li "URL 2" 
    [:ul 
    [:li "indirect 1"] 
    [:li "indirect 2"]]]]] 

Diese Ausgabe von Ihrer erwarteten Ausgabe etwas anders, aber ich denke, es ist näher an, was Sie eigentlich wollen würden also der [:li "URL 2"]-Tag in Ihrem Beispiel soll die :ul von „Indirects“ enthält gültige HTML zu sein .

Eine andere Sache, die vorsichtig sein sollte, wenn die Reihenfolge dieser Elemente wichtig ist, ist, dass Karten nicht in der Art und Weise, wie Sie erwarten, besonders wenn Sie über eine bestimmte Anzahl von Schlüsseln verfügen. Wenn Sie die Karte durchlaufen, um Schluckauf zu bauen, ist es möglich, dass "URL 2"vor"URL 1" kommen konnte. Sie können dies umgehen, indem Sie einen Vektor von Tupeln oder eine sortierte Karte verwenden.

+0

Das hat perfekt funktioniert, vielen Dank! Ich glaube, ich habe versucht, zu viel in eine Funktion zu stecken. Ich habe nicht einmal daran gedacht, mapv zu benutzen, aber es scheint jetzt so offensichtlich zu sein :) –

Verwandte Themen