2

在 Clojure 中合并两个映射列表的惯用方式是什么,其中每个映射条目都由一个 id 键标识?

什么是foo这样的实现

(foo '({:id 1 :bar true :value 1} 
       {:id 2 :bar false :value 2} 
       {:id 3 :value 3})
     '({:id 5 :value 5} 
       {:id 2 :value 2} 
       {:id 3 :value 3}
       {:id 1 :value 1} 
       {:id 4 :value 4})) => '({:id 1 :bar true :value 1}
                               {:id 2 :bar false :value 2}
                               {:id 3 :value 3}
                               {:id 4 :value 4}
                               {:id 5 :value 5})

是真的?

4

3 回答 3

2
(defn merge-by
  "Merges elems in seqs by joining them on return value of key-fn k.
   Example: (merge-by :id [{:id 0 :name \"George\"}{:id 1 :name \"Bernie\"}]
                          [{:id 2 :name \"Lara\"}{:id 0 :name \"Ben\"}])
   => [{:id 0 :name \"Ben\"}{:id 1 :name \"Bernie\"}{:id 2 :name \"Lara\"}]"
  [k & seqs]
  (->> seqs
       (map (partial group-by k))
       (apply merge-with (comp vector
                               (partial apply merge)
                               concat))
       vals
       (map first)))
于 2013-08-21T23:07:52.757 回答
1

This is generalized so that you can have an arbitrary number of input sequences, and an arbitrary grouping selector:

(def a [{:id 5 :value 5} 
        {:id 2 :value 2} 
        {:id 3 :value 3}
        {:id 1 :value 1} 
        {:id 4 :value 4}])

(def b [{:id 1 :bar true :value 1} 
        {:id 2 :bar false :value 2} 
        {:id 3 :value 3}])

(def c [{:id 1 :bar true :value 1}
        {:id 2 :bar false :value 2}
        {:id 3 :value 3}
        {:id 4 :value 4}
        {:id 5 :value 5}])

(defn merge-vectors
  [selector & sequences]
  (let [unpack-grouped (fn [group]
                         (into {} (map (fn [[k [v & _]]] [k v]) group)))
        grouped (map (comp unpack-grouped (partial group-by selector))
                     sequences)
        merged (apply merge-with merge grouped)]
    (sort-by selector (vals merged))))

(defn tst
  []
  (= c
   (merge-vectors :id a b)))
于 2013-08-21T17:08:52.320 回答
1

这个怎么样:

(defn foo [& colls]
  (map (fn [[_ equivalent-maps]] (apply merge equivalent-maps)) 
       (group-by :id (sort-by :id (apply concat colls)))))
于 2013-08-21T17:50:56.940 回答