Clojure merge multiple map into a single map

我是研究僧i 提交于 2021-02-06 15:21:13

问题


I have the following list of maps

({"child.search" {:roles #{"ROLE_ADM_UNSUBSCRIBE_SUBSCRIPTION" "ROLE_ADM_SEARCH_SUBSCRIPTION" "ROLE_ADM_VIEW_SUBSCRIPTION"}},
  "child.cc.search" {:roles #{"ROLE_ADM_CC_SEARCH_SUBSCRIPTION" "ROLE_ADM_CC_VIEW_SUBSCRIPTION"}}}
  {"child.abusereport" {:roles #{"ROLE_ADM_ABUSE_RPT"}},
   "child.manualfiltering" {:roles #{"ROLE_ADM_MANUAL_FILTERING_RPT"}}}
  {"child.assigned.advertisement" {:roles #{"ROLE_ADM_CREATE_ADVERTISING"}},
   "child.manage.advertisement" {:roles #{"ROLE_ADM_LIST_ADVERTISING"}}})

I need to have a single map like following.

{"child.search" {:roles #{"ROLE_ADM_UNSUBSCRIBE_SUBSCRIPTION" "ROLE_ADM_SEARCH_SUBSCRIPTION" "ROLE_ADM_VIEW_SUBSCRIPTION"}}
"child.cc.search" {:roles #{"ROLE_ADM_CC_SEARCH_SUBSCRIPTION" "ROLE_ADM_CC_VIEW_SUBSCRIPTION"}}
"child.abusereport" {:roles #{"ROLE_ADM_ABUSE_RPT"}}
"child.manualfiltering" {:roles #{"ROLE_ADM_MANUAL_FILTERING_RPT"}}
"child.assigned.advertisement" {:roles #{"ROLE_ADM_CREATE_ADVERTISING"}}
"child.manage.advertisement" {:roles #{"ROLE_ADM_LIST_ADVERTISING"}}}

How can I do it?


回答1:


You can use the "into" function, and supply an empty map {} as the first argument:

(into {} map-list)

Here's the output from my REPL session; I copied your code into two vars 'map-list' and 'single-map' (Clojure 1.3.0):

(def map-list '({"child.search" {:roles #{"ROLE_ADM_UNSUBSCRIBE_SUBSCRIPTION" "ROLE_ADM_SEARCH_SUBSCRIPTION" "ROLE_ADM_VIEW_SUBSCRIPTION"}},
                 "child.cc.search" {:roles #{"ROLE_ADM_CC_SEARCH_SUBSCRIPTION" "ROLE_ADM_CC_VIEW_SUBSCRIPTION"}}}
                {"child.abusereport" {:roles #{"ROLE_ADM_ABUSE_RPT"}},
                 "child.manualfiltering" {:roles #{"ROLE_ADM_MANUAL_FILTERING_RPT"}}}
                {"child.assigned.advertisement" {:roles #{"ROLE_ADM_CREATE_ADVERTISING"}},
                 "child.manage.advertisement" {:roles #{"ROLE_ADM_LIST_ADVERTISING"}}}))

#'user/map-list
user=>
(def single-map {"child.search" {:roles #{"ROLE_ADM_UNSUBSCRIBE_SUBSCRIPTION" "ROLE_ADM_SEARCH_SUBSCRIPTION" "ROLE_ADM_VIEW_SUBSCRIPTION"}}
                 "child.cc.search" {:roles #{"ROLE_ADM_CC_SEARCH_SUBSCRIPTION" "ROLE_ADM_CC_VIEW_SUBSCRIPTION"}}
                 "child.abusereport" {:roles #{"ROLE_ADM_ABUSE_RPT"}}
                 "child.manualfiltering" {:roles #{"ROLE_ADM_MANUAL_FILTERING_RPT"}}
                 "child.assigned.advertisement" {:roles #{"ROLE_ADM_CREATE_ADVERTISING"}}
                 "child.manage.advertisement" {:roles #{"ROLE_ADM_LIST_ADVERTISING"}}})
#'user/single-map

user=>
;; Check to see if we have the desired result
(= (into {} map-list)
   single-map)
true



回答2:


I would probably use merge and apply

(def map-list (list {:a 1, :b 2} {:c 3, :d 4}))
(apply merge map-list) ;; returns {:a 1, :b 2, :c 3, :d 4}



回答3:


Try this

(def your-list '({"child.search" {:roles #{"ROLE_ADM_UNSUBSCRIBE_SUBSCRIPTION" "ROLE_ADM_SEARCH_SUBSCRIPTION" "ROLE_ADM_VIEW_SUBSCRIPTION"}},
  "child.cc.search" {:roles #{"ROLE_ADM_CC_SEARCH_SUBSCRIPTION" "ROLE_ADM_CC_VIEW_SUBSCRIPTION"}}}
  {"child.abusereport" {:roles #{"ROLE_ADM_ABUSE_RPT"}},
   "child.manualfiltering" {:roles #{"ROLE_ADM_MANUAL_FILTERING_RPT"}}}
  {"child.assigned.advertisement" {:roles #{"ROLE_ADM_CREATE_ADVERTISING"}},
   "child.manage.advertisement" {:roles #{"ROLE_ADM_LIST_ADVERTISING"}}}))

(reduce conj your-list)



回答4:


This answer clarifies the way that "into" and "conj" interrelate in this instance to both provide acceptable solutions to your problem. That is, it stands on the shoulders of the previous answers..

You have a list which is of the format :

( {key1 value1} 
  {key2 value2} ) 

And you want a map which has extracted the key/value pairs as follows:

{key1 value1, key2 value2} 

The problem, then, is that you essentially want to "conjoin" each successive k/v pair to the last, in a single map.

The 1st solution above does this using into. If we look at the clojuredoc for into, we see:

"Returns a new coll consisting of to-coll with all of the items of
from-coll conjoined."

The other, similar answer is to use

(reduce conj '({key1 value1} {key2 value2}))

Clearly, this solution is spelling out the "into" definition above for this problem : the reduce function accumulates each application of the conjoining of the nth + (nth+1th) key value pair, such that it implements the definition for into (at least, for the purposes of this question).



来源:https://stackoverflow.com/questions/9545778/clojure-merge-multiple-map-into-a-single-map

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!