Clojure - 将平面地图转换为具有预定结构的嵌套
Clojure - transform flat map to nested with predecided structure
我是 clojure 的新手,我正在尝试将特定格式的消息转换为另一种格式。
即,我必须转换如下内容:
{
:image-url ["https://image.png"],
:topic "Some title",
:id "88ebaf91-a01d-4683-9aa7-629bb3ecea01",
:short-description "Some Description",
:mobile-deeplink "https://deeplink.com/link",
:partner-name "partner"}
变成类似
的东西
{
:title "Some title",
:id "88ebaf91-a01d-4683-9aa7-629bb3ecea01",
:content {
:url ["https://image.png"],
:description "Some Description",
:deeplink "https://deeplink.com/link",
:partner "partner"}}
所以实际上,有重命名键和嵌套平面地图的组合
到目前为止我所做的是:
(let [message-map {
:image-url :purl
:topic :title
:partner-name :partner
:short-description :description
:mobile-deeplink :deeplink}]
(defn- map-to-body
[message]
(-> message
(clojure.set/rename-keys message-map)
;;some sort of (assoc-in) <- this is where i need help in
)))
你可以在这里链接-assoc-in
,但我认为你更轻松
使用 select-keys
。 select-keys
让您只提取密钥
从一张地图变成一张新地图,你需要。所以你可以 select :id
/:title
外部地图和其余地图关联到 :content
.
例如
(require 'clojure.set)
(defn transform
[message]
(let [message-map {:image-url :url
:topic :title
:partner-name :partner
:short-description :description
:mobile-deeplink :deeplink}
renamed (clojure.set/rename-keys message message-map)]
(assoc ; XXX
(select-keys renamed [:title :id])
:content (select-keys renamed [:url :description :deeplink :partner]))))
(def src {:image-url ["https://image.png"],
:topic "Some title",
:id "88ebaf91-a01d-4683-9aa7-629bb3ecea01",
:short-description "Some Description",
:mobile-deeplink "https://deeplink.com/link",
:partner-name "partner"})
(def tgt {:title "Some title",
:id "88ebaf91-a01d-4683-9aa7-629bb3ecea01",
:content {
:url ["https://image.png"],
:description "Some Description",
:deeplink "https://deeplink.com/link",
:partner "partner"}})
(assert (= (transform src) tgt))
组合 assoc-in
、路径转换 table 和 reduce
可能更 self-describing 和可维护。您可以选择减少转换 table 或输入消息,以对您拥有的数据更有意义的为准。
(defn transform [m]
(let [pp '([:image-url [:content :url]]
[:topic [:title]]
[:id [:id]]
[:short-description [:content :description]]
;; etc.
)]
(reduce
(fn [o [mk ok]]
(assoc-in o ok (get m mk)))
{}
pp)))
我是 clojure 的新手,我正在尝试将特定格式的消息转换为另一种格式。
即,我必须转换如下内容:
{
:image-url ["https://image.png"],
:topic "Some title",
:id "88ebaf91-a01d-4683-9aa7-629bb3ecea01",
:short-description "Some Description",
:mobile-deeplink "https://deeplink.com/link",
:partner-name "partner"}
变成类似
的东西{
:title "Some title",
:id "88ebaf91-a01d-4683-9aa7-629bb3ecea01",
:content {
:url ["https://image.png"],
:description "Some Description",
:deeplink "https://deeplink.com/link",
:partner "partner"}}
所以实际上,有重命名键和嵌套平面地图的组合
到目前为止我所做的是:
(let [message-map {
:image-url :purl
:topic :title
:partner-name :partner
:short-description :description
:mobile-deeplink :deeplink}]
(defn- map-to-body
[message]
(-> message
(clojure.set/rename-keys message-map)
;;some sort of (assoc-in) <- this is where i need help in
)))
你可以在这里链接-assoc-in
,但我认为你更轻松
使用 select-keys
。 select-keys
让您只提取密钥
从一张地图变成一张新地图,你需要。所以你可以 select :id
/:title
外部地图和其余地图关联到 :content
.
例如
(require 'clojure.set)
(defn transform
[message]
(let [message-map {:image-url :url
:topic :title
:partner-name :partner
:short-description :description
:mobile-deeplink :deeplink}
renamed (clojure.set/rename-keys message message-map)]
(assoc ; XXX
(select-keys renamed [:title :id])
:content (select-keys renamed [:url :description :deeplink :partner]))))
(def src {:image-url ["https://image.png"],
:topic "Some title",
:id "88ebaf91-a01d-4683-9aa7-629bb3ecea01",
:short-description "Some Description",
:mobile-deeplink "https://deeplink.com/link",
:partner-name "partner"})
(def tgt {:title "Some title",
:id "88ebaf91-a01d-4683-9aa7-629bb3ecea01",
:content {
:url ["https://image.png"],
:description "Some Description",
:deeplink "https://deeplink.com/link",
:partner "partner"}})
(assert (= (transform src) tgt))
组合 assoc-in
、路径转换 table 和 reduce
可能更 self-describing 和可维护。您可以选择减少转换 table 或输入消息,以对您拥有的数据更有意义的为准。
(defn transform [m]
(let [pp '([:image-url [:content :url]]
[:topic [:title]]
[:id [:id]]
[:short-description [:content :description]]
;; etc.
)]
(reduce
(fn [o [mk ok]]
(assoc-in o ok (get m mk)))
{}
pp)))