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-keysselect-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)))