Clojure объединяет несколько карт в одну карту - PullRequest
13 голосов
/ 03 марта 2012

У меня есть следующий список карт

({"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"}}})

Мне нужна одна карта, подобная следующей.

{"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"}}}

Как мне это сделать?

Ответы [ 4 ]

11 голосов
/ 03 марта 2012

Вы можете использовать функцию " into " и предоставить пустую карту {} в качестве первого аргумента:

(into {} map-list)

Вот вывод из моей сессии REPL; Я скопировал ваш код в две переменные 'map-list' и 'single-map' (Clojure 1.3.0):

* * 1010
7 голосов
/ 04 марта 2012

Я бы, наверное, использовал merge и 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}
2 голосов
/ 03 марта 2012

Попробуйте это

(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)
0 голосов
/ 30 июня 2012

Этот ответ проясняет способ, которым «в» и «кон» взаимосвязаны в данном случае, чтобы обеспечить приемлемые решения вашей проблемы.То есть он стоит на плечах предыдущих ответов ..

У вас есть список в формате:

( {key1 value1} 
  {key2 value2} ) 

И вам нужна карта, которая извлекла ключ /Пары значений следующим образом:

{key1 value1, key2 value2} 

Проблема в том, что вы, по сути, хотите «соединить» каждую последующую пару k / v с последней в одной карте.

1-е решение выше использует это в.Если мы посмотрим на clojuredoc для into, мы увидим:

"Возвращает новый coll, состоящий из to-coll со всеми элементами
, соединенными из-coll."

Другой, аналогичный ответ заключается в использовании

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

. Очевидно, что это решение излагает вышеприведенное определение «в» для этой задачи: функция сокращения накапливает каждое применение объединенияnth + (nth + 1th) пара значений ключа, так что она реализует определение для в (по крайней мере, для целей этого вопроса).

...