2012-06-27 88 views
1

我有一系列地圖。將地圖序列轉換爲多地圖

;; input 
[{:country "MX", :video 12345, :customer "cid1"} 
{:country "US", :video 12345, :customer "cid2"} 
{:country "MX", :video 54321, :customer "cid1"}] 

我想將它轉換成一個multimap。我想生成。

;; output 
{"cid1" 
    {:actions 
      [{:country "MX", :video 12345, :customer "cid1"} 
      {:country "MX", :video 12345, :customer "cid1"}]}, 
"cid2" 
    {:actions 
      [{:country "US", :video 12345, :customer "cid2"}]}} 

我覺得我應該使用update-in。有些事情......我只是沒有弄清楚some-fn-here的樣子,我想其他人可能會有同樣的問題。

(defn add-mm-entry 
    [m e] 
    (update-in m [(:customer e)] some-fn-here)) 

(def output (reduce add-mm-entry {} input)) 

想象一下,當我工作時,我會把它扔給社區。如果我在這裏走錯了路,讓我知道。

回答

5

如果我正確理解了意圖,則按以下方式進行分組:客戶,然後將行爲向量包裝到:actions中。您可以通過組做分組與clojure.core /然後映射(clojure.core /圖)結果:

(def v [{:country "MX", :video 12345, :customer "cid1"} 
     {:country "US", :video 12345, :customer "cid2"} 
     {:country "MX", :video 54321, :customer "cid1"}]) 

(->> v 
    (group-by :customer) 
    (map (fn [[cid xs]] {cid {:actions xs}})) 
    (into {})) 
+1

最終輸出應該是一張地圖,所以你需要通過'(到{})'運行結果。 –

2

邁克爾的回答運作良好。我不確定group-by是否適合我的具體情況,因爲我正在加載的數據的大小。我沒有測試過,但我認爲這種方法會導致中間產品減少。

(def v [{:country "MX", :video 12345, :customer "cid1"} 
     {:country "US", :video 12345, :customer "cid2"} 
     {:country "MX", :video 54321, :customer "cid1"}]) 

(defn add-entry 
    [m e] 
    (let [cust (:customer e)] 
     (update-in m [cust :actions] #(conj % e)))) 

(reduce add-entry {} v) 

仍導致完整的數據集被加載,但它被直接加載到目標數據結構,而不是插入的地圖的矢量,然後進入一個多重映射。再一次,我沒有測試過哪一個是明確更高性能的,但是看起來這個數據集的迭代次數少了一次,並且避免了創建來自group-by的不需要的映射向量。