合并两个地图列表,将地图组合在一个特定的键上

时间:2013-12-27 21:08:57

标签: clojure

我正在对Cassandra运行两个select语句,所以我没有加入,而是需要在代码中加入它们。作为Clojure相对较新,我很难做到这一点,而不需要使用非常丑陋的嵌套循环。此外,如果table-b缺少来自table-a的匹配条目,则它应该添加默认的table-b值。

两个选择地图列表中的每个结果(每个“行”是一个地图)。 id键是UUID,而不是字符串。

如果我对具有相同结构的东西进行定义,那么这些选择是如何看的。

(def table-a (list {:id "105421db-eca4-4500-9a2c-08f1e09a35ca" :col-b "b-one"}
                   {:id "768af3f3-3981-4e3f-a93d-9758cd53a056" :col-b "b-two"}))

(def table-b (list {:id "105421db-eca4-4500-9a2c-08f1e09a35ca" :col-c "c-one"}))

我希望最终结果如下:

({:id "105421db-eca4-4500-9a2c-08f1e09a35ca" :col-b "b-one" :col-c "c-one"}
 {:id "768af3f3-3981-4e3f-a93d-9758cd53a056" :col-b "b-two" :col-c "default-value"})

感谢您的帮助。

1 个答案:

答案 0 :(得分:10)

这可以通过将其拆分为具有相同键的组来完成,合并所有类似键控的映射,然后填写默认值:

user> (->> (concat table-a table-b)     ;; stat with all the data
           (sort-by :id)                ;; split it into groups
           (partition-by :id)           ;; by id
           (map (partial apply merge))  ;; merge each group into a single map.
           (map #(assoc %               ;; fill in the missing default values.
                    :col-c (or (:col-c %) "default value") 
                    :col-b (or (:col-b %) "default value"))))

({:col-c "c-one", 
  :col-b "b-one", 
  :id "105421db-eca4-4500-9a2c-08f1e09a35ca"} 
 {:col-c "default value", 
  :col-b "b-two", 
  :id "768af3f3-3981-4e3f-a93d-9758cd53a056"})

使用线程最后一个宏->>使我更容易阅读,尽管这只是我的观点。还有一种更优雅的方式来提供默认密钥。