변환 기능을 :tags
에 입력 한 다음 :metrics
을 입력 한 다음 :sources
을 입력하면됩니다. 이제 우리는 단지 태그를 계산하여 기능 ID를 생성 변환 가정 해 봅시다
는
(단지 그림을 위해, 나중에 쉽게 변경 될 수 있습니다) : 지금
(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}
:
(defn transform [tags] (count tags))
user> (transform ["asd" "dsf"])
;;=> 2
다음 변환에게 통계 항목을 적용 소스 항목을 업데이트하려면 transform-metric
을 사용하십시오.
(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}]}
및 마지막 단계는 전체 데이터를 변환하는 것입니다 :
(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}]}]}
그래서 여기서 끝났습니다.
지금 transform-data
및 transform-source
거의 동일하다는 것을 발견, 그래서 우리는 업데이트 기능을 생성하는 유틸리티 기능을 할 수 있습니다 : 우리는 다음과 같이 깊은 변환을 정의 할 수 있습니다이 기능을
(defn make-vec-updater [field transformer]
(fn [data] (update data field (partial mapv transformer))))
을 :
(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}]}]}
이 트랜스포머 구성 방법을 기반으로 우리는 vector of-maps-of-vectors-of-vectors의 값을 업데이트하는 멋진 함수를 만들 수 있습니다 ...임의의 중첩 수준과 구조 :
(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
이 매뉴얼 방식뿐만 아니라, 정확히 같은 일을 (그리고 더 많은) 거기 specter라는 환상적인 LIB가있다, 하지만 분명 더 보편적이고 사용할 수 :
(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}]}]}
브래킷의 균형을 맞추기 위해 질문을 편집 할 때 잘못된 수리를했을 수도 있습니다. 원래의 데이터와 원하는 데이터 모두에는 하나의 요소 만있는': sources' 벡터가 있습니다. 그것은 벡터입니까, 아니면 여분의 여는 대괄호를 제거 했어야합니까? – Thumbnail
': sources' 키의 값은 맵의 벡터입니다. 그것이 지금 나에게 좋게 보이는 방법. –