将一系列地图转换为多图

时间:2012-06-27 04:40:55

标签: clojure multimap

我有一系列地图。

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

我想将其转换为多图。我想生成。

;; 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))

想在我工作的时候,我会把它扔给社区。如果我走错了路,请告诉我。

2 个答案:

答案 0 :(得分:5)

如果我正确理解了意图,那么您将按以下方式进行分组:客户然后将操作向量包装到:actions。您可以使用 clojure.core / group-by 进行分组,然后映射( clojure.core / map )结果:

(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的不需要的地图矢量。