2017-08-15 1 views
2

Wie könnte man die folgende Transformation in idiomatischer Clojure ausdrücken?Verschachtelte Map zu Sequenz von Tupeln, die Kanten in Clojure darstellen

(def m 
    {:a {:b {:c nil 
       :d nil}} 
      :e nil}}) 


(map->edges m) ; => 


([:a :b] [:b :c] [:b :d] [:e nil] [:d nil] [:a :e] [:e nil]) 

Ich interessiere mich nicht über die Reihenfolge, in den Vektoren im Ergebnis erscheinen, also entweder zuerst in der Tiefe oder Atem ersten Suchstrategien sind in Ordnung.

+1

FWIW das Eingabeformat ist nicht wirklich ein sehr guter Weg, um eine grafische Darstellung der Darstellung, da es nicht ist klar, wie Zyklen funktionieren werden. Typischer ist etwas wie eine Adjazenzkarte, wo die Schlüssel Knoten und Werte Gruppen von Knoten sind. Für Ihr Diagramm würde das aussehen wie "{a # {b e}, b # {c d}}", optional mit leeren Mengen für c/d/e, um Knoten ohne ausgehende Kanten anzugeben. Idealerweise würde ich sagen, dass Sie Ihr Eingabeformat korrigieren müssen, damit Sie diesen Schritt nicht machen müssen, aber wenn Sie es nicht kontrollieren können, dann sind die Antworten auf diese Frage ein vernünftiger Weg, um es nachzubearbeiten. – amalloy

Antwort

8

können Sie dies ausdrücken ziemlich prägnant mit for und tree-seq:

(defn map->edges [m] 
    (for [entry m 
     [x m] (tree-seq some? val entry) 
     y (or (keys m) [m])] 
    [x y])) 

Beispiel:

(map->edges m) 
;;=> ([:a :b] [:a :e] [:b :c] [:b :d] [:c nil] [:d nil] [:e nil]) 
Verwandte Themen