Я не думаю, что есть какая-то простая функция, которая уже делает это, но я могу ошибаться.
Если вы знаете, что каждый user_id
существует в каждой последовательности, то вы можете просто сортировать по user_id
, а затем применить сливаться в соответствующие карты:
(defn sort-by-user-id
[m]
(sort #(< (:user_id %1) (:user_id %2)) m))
(map merge (sort-by-user-id a) (sort-by-user-id b))
; => ({:email "e 1", :name "user 1", :user_id 1} {:email "e 2", :name "user 2", :user_id 2})
Если вы не можете предположить, что все же user_id
существуют в каждой последовательности, я думаю, вам нужно сделать что-то немного сложнее, чтобы соответствовать user_id
s. Я предполагаю, что если карта имени не имеет соответствующей карты электронной почты, вы хотите оставить карту имен без изменений (или наоборот для отсутствующих карт имен). Если нет, то одним из вариантов будет удаление этих карт и использование метода, приведенного выше.
Здесь вы можете объединить соответствующие названия и карты электронной почты. Мы можем использовать user_id
s как ключи в карте карт, чтобы соответствовать соответствующим картам. Сначала создает карту, содержащую все карты с user_ids как ключи, например, так:
(def az (zipmap (map :user_id a) a)) ; => {2 {:name "user 2", :user_id 2}, 1 {:name "user 1", :user_id 1}}
(def bz (zipmap (map :user_id b) b)) ; => {1 {:email "e 1", :user_id 1}, 2 {:email "e 2", :user_id 2}}
Затем объединить отдельные карты, как это, обнажая из ключей в конце процесса:
(vals (merge-with merge az bz))
; => ({:email "e 2", :name "user 2", :user_id 2} {:email "e 1", :name "user 1", :user_id 1})
Собираем все вместе:
(defn map-of-maps
[cm]
(zipmap (map :user_id cm) cm))
(defn merge-maps
[& cms]
(vals
(apply merge-with merge
(map map-of-maps cms))))
Давайте удостоверимся, что он работает с отсутствующими user_id
S:
(def a+ (conj a {:name "user 3", :user_id 3}))
(def b+ (conj b {:email "e 4", :user_id 4}))
(merge-maps a+ b+)
; => ({:email "e 4", :user_id 4} {:name "user 3", :user_id 3} {:email "e 2", :name "user 2", :user_id 2} {:email "e 1", :name "user 1", :user_id 1})
Я не удивлюсь, если есть более простые или более элегантные методы. Это только одна стратегия, которая пришла мне в голову.
Af ter Я отправил свой ответ, я заметил [этот вопрос] (http://stackoverflow.com/questions/10209218/clojure-merging-two-array-of-maps). Я не уверен, что вопрос строго один и тот же; непонятно, что задается, потому что пример перезаписывает значение одного ключа (': b' на карте, содержащей' 2' для ': a'). Однако ответы на вопрос - это ответы на ваш вопрос. Поэтому я думаю, что это считается дублирующим вопросом. Поскольку мой ответ отличается, я оставил его здесь, но, может быть, я должен отправить его другому вопросу? Не уверен. – Mars