Ich würde von unten nach oben starten, Transformationsfunktion für :tags
Eintrag machen, dann für :metrics
und dann für :sources
.
(defn transform [tags] (count tags))
user> (transform ["asd" "dsf"])
;;=> 2
dann gelten Umwandlung der Metrik Eintrag:
(defn transform-metric [{:keys [tags] :as m}]
(assoc m :id (transform tags)))
user> (transform-metric {:tags ["a noether tag" "aegn"]})
;;=> {:tags ["a noether tag" "aegn"], :id 2}
jetzt
sagen wir unsere Funktion Tags durch Zählen ids Transformation nur produziert (nur zur Veranschaulichung, es später leicht geändert werden könnte) verwenden transform-metric
Source-Eintrag zu aktualisieren:
(defn transform-source [s]
(update s :metrics #(mapv transform-metric %)))
user> (transform-source {:tags ["s:my:tags"],
:metrics [{:tags ["a tag"]}
{:tags ["a noether tag" "aegn"]}
{:tags ["eare" "rh"]}]})
;;=> {:tags ["s:my:tags"],
;; :metrics [{:tags ["a tag"], :id 1}
;; {:tags ["a noether tag" "aegn"], :id 2}
;; {:tags ["eare" "rh"], :id 2}]}
und Der letzte Schritt besteht darin, die gesamten Daten zu transformieren:
(defn transform-data [d]
(update d :sources #(mapv transform-source %)))
user> (transform-data data)
;;=> {:tags ["type:something" "gw:somethingelse"],
;; :sources [{:tags ["s:my:tags"],
;; :metrics [{:tags ["a tag"], :id 1}
;; {:tags ["a noether tag" "aegn"], :id 2}
;; {:tags ["eare" "rh"], :id 2}]}]}
Also, wir sind hier fertig.
nun feststellen, dass transform-data
und transform-source
fast identisch sind, so können wir eine Nutzenfunktion machen, die solche Aktualisierung Funktionen erzeugt:
(defn make-vec-updater [field transformer]
(fn [data] (update data field (partial mapv transformer))))
Mit dieser Funktion können wir tiefe Transformationen wie folgt definieren:
(def transformer
(make-vec-updater
:sources
(make-vec-updater
:metrics
(fn [{:keys [tags] :as m}]
(assoc m :id (transform tags))))))
user> (transformer data)
;;=> {:tags ["type:something" "gw:somethingelse"],
;; :sources [{:tags ["s:my:tags"],
;; :metrics [{:tags ["a tag"], :id 1}
;; {:tags ["a noether tag" "aegn"], :id 2}
;; {:tags ["eare" "rh"], :id 2}]}]}
und basierend auf dieser Transformatorkonstruktion Ansatz können wir eine nette Funktion machen, um die Werte in Vektoren-von-Karten-von-Vektoren-von-Karten-von-Vektoren zu aktualisieren ...Strukturen, mit beliebiger Verschachtelungsebene:
(defn update-in-v [data ks f]
((reduce #(make-vec-updater %2 %1) f (reverse ks)) data))
user> (update-in-v data [:sources :metrics]
(fn [{:keys [tags] :as m}]
(assoc m :id (transform tags))))
;;=> {:tags ["type:something" "gw:somethingelse"],
;; :sources [{:tags ["s:my:tags"],
;; :metrics [{:tags ["a tag"], :id 1}
;; {:tags ["a noether tag" "aegn"], :id 2}
;; {:tags ["eare" "rh"], :id 2}]}]}
UPDATE
zusätzlich zu diesem Handbuch Ansatz gibt es eine fantastische lib specter gibt, die genau tut die gleiche Sache (und vieles mehr) genannt wird, aber ist offensichtlich universellere und verwendbar:
(require '[com.rpl.specter :as sp])
(sp/transform [:sources sp/ALL :metrics sp/ALL]
(fn [{:keys [tags] :as m}]
(assoc m :id (transform tags)))
data)
;;=> {:tags ["type:something" "gw:somethingelse"],
;; :sources [{:tags ["s:my:tags"],
;; :metrics [{:tags ["a tag"], :id 1}
;; {:tags ["a noether tag" "aegn"], :id 2}
;; {:tags ["eare" "rh"], :id 2}]}]}
Bei der Bearbeitung Ihrer Frage, um die Klammern auszubalancieren, befürchte ich, dass ich die falsche Reparatur gemacht habe. Sowohl die ursprünglichen als auch die gewünschten Daten haben einen Vektor ': sources' mit nur einem Element. Ist es ein Vektor oder hätte ich die überflüssige öffnende eckige Klammer entfernen sollen? – Thumbnail
Der Wert für den Schlüssel ': sources' ist ein Vektor von Maps. So wie es jetzt aussieht, sieht es gut für mich aus. –