2012-04-18 106 views
4

的我有地圖的兩個陣列Clojure中,合併兩個陣列地圖

第一是[{:a 1 :b 2 :d 6} {:a 2 :b 2} {:a 7 :b 7}]

第二是[{:a 3 :c 3 :e 9 :y 7} {:a 2 :b 6 :c 8}]

取決於如果a即值及其在第二陣列的「第二匹配地圖第一地圖‘和圖的合成陣列」應被合併’應該是

RES應[{:a 1 :b 2 :d 6} {:a 2 :b 6 :c 8} {:a 7 :b 7} {:a 3 :c 3 :e 9 :y 7}]

任何人都可以幫助我解決這個問題。提前致謝。

+0

我不太清楚是什麼換句話說,算法是,我不太清楚你在比較什麼來獲得「Res」。 – octopusgrabbus 2012-04-18 12:59:41

+0

我正在比較關鍵'a'的值。如果第一個地圖中'a'的val與第二個數組中任一個地圖中'a'的值匹配,則執行此操作(合併{第一個地圖具有'a'值= 1} {第二個地圖具有'a'值= 1 })並將此結果地圖添加到最終地圖 – Avi 2012-04-18 13:00:30

回答

4

這個數據結構看起來很笨拙我不過這是我的看法:

(defn key-by-a [coll] 
    "Convert a list of maps to a map of maps keyed by their vals at :a" 
    (apply hash-map (mapcat (juxt :a identity) coll))) 

(defn merge-map-lists [l1 l2] 
    (->> [l1 l2] 
    (map key-by-a) 
    (apply merge-with merge) 
    (vals))) 

一兩件事沒有做到的是保持輸入列表的順序,但因爲它是不清楚哪個列表決定(既可能有不同的順序相同的鍵)我離開了。

6

在這裏你去:

user> (def xs [{:a 1 :b 2 :d 6} {:a 2 :b 2} {:a 7 :b 7}]) 
#'user/xs 
user> (def ys [{:a 3 :c 3 :e 9 :y 7} {:a 2 :b 6 :c 8}]) 
#'user/ys 
user> (for [[a ms] (group-by :a (concat xs ys))] (apply merge ms)) 
({:a 1, :b 2, :d 6} {:a 2, :c 8, :b 6} {:a 7, :b 7} {:y 7, :a 3, :c 3, :e 9}) 
0

也許clojure.set /加盟是你想要什麼:

這裏是clojure.set/join文檔:

user=> (def animals #{{:name "betsy" :owner "brian" :kind "cow"} 
         {:name "jake" :owner "brian" :kind "horse"} 
         {:name "josie" :owner "dawn" :kind "cow"}}) 

user=> (def personalities #{{:kind "cow" :personality "stoic"} 
          {:kind "horse" :personality "skittish"}}) 
#'user/personalities 
user=> (join animals personalities) 

#{{:owner "dawn", :name "josie", :kind "cow", :personality "stoic"} 
    {:owner "brian", :name "betsy", :kind "cow", :personality "stoic"} 
    {:owner "brian", :name "jake", :kind "horse", :personality "skittish"}} 

user=> (join animals personalities) 
#{{:kind "horse", :owner "brian", :name "jake", :species "cow", :personality "stoic"} 
    {:kind "cow", :owner "dawn", :name "josie", :species "cow", :personality "stoic"} 
    {:kind "horse", :owner "brian", :name "jake", :species "horse", :personality "skittish"} 
    {:kind "cow", :owner "brian", :name "betsy", :species "cow", :personality "stoic"} 
    {:kind "cow", :owner "dawn", :name "josie", :species "horse", :personality "skittish"} 
    {:kind "cow", :owner "brian", :name "betsy", :species "horse", :personality "skittish"}} 


;; Notice that "Jake" is both a horse and a cow in the first line. That's 
;; likely not what you want. You can tell `join` to only produce output 
;; where the `:kind` value is the same as the `:species` value like this: 

user=> (join animals personalities {:kind :species}) 
#{{:kind "cow", :owner "dawn", :name "josie", :species "cow", :personality "stoic"} 
    {:kind "horse", :owner "brian", :name "jake", :species "horse", :personality "skittish"} 
    {:kind "cow", :owner "brian", :name "betsy", :species "cow", :personality "stoic"}}