我有一份地图清单:
(( {:id 1 :temp 1} {:id 2} )
( {:id 1 :temp 2} )
( {:id 1 :temp 3} {:id 2} ))
我想通过:id
键获取这3组交集的ID。所以我的结果将是1
我提出了这个解决方案,但它伤害了我的眼睛:
(def coll '(( {:id 1 :temp 1} {:id 2} )
( {:id 1 :temp 2} )
( {:id 1 :temp 3} {:id 2} )))
(apply clojure.set/intersection
(map set (map (fn [m]
(map #(select-keys % '(:id)) m)) coll)))
返回
#{{:id 1}}
这是好的,但是还有其他建议吗?
答案 0 :(得分:0)
如果你可以获得#{1}
(正如你最初提到的那样)而不是#{{:id 1}}
,那么它可以稍微改进一下:
(apply set/intersection (map (fn [c] (into #{} (map :id c))) coll))
答案 1 :(得分:0)
(require '[clojure.set :refer [intersection]])
我猜你不需要的选择键,因为你只对id感兴趣。 (map :id m)
完成最内层地图的工作。通过这个你摆脱了一个功能速记。您可以在下一张地图中使用它:
(map #(map :id %) coll)
;; ((1 2) (1) (1 2))
您介绍的第三张地图不是必需的。它可以在上面的代码中合并:
(map (comp set #(map :id %)) coll)
或:
(map #(set (map :id %)) coll)
评估为:(#{1 2} #{1} #{1 2})
这仍然是非常嵌套的。线程宏在这里没有帮助。但是你可以使用一个名为for
的非常强大的列表推导宏:
(for [row coll]
(set (map :id row)))
这为您提供了命名列表项(行)但同时保持简洁的优势。
最后:
(apply intersection (for [row coll]
(set (map :id row))))
;; #{1}