1

例如,假设我有两组:

(def set-a #{{:id 1 :name "ABC" :zip 78759} {:id 2 :name "DEF" :zip 78759}})

(def set-b #{{:id 1 :name "ABC" :zip 78753} {:id 3 :name "XYZ" :zip 78704}})

我想在集合之间找到一个联合,只使用 :id 和 :name 字段。但是,如果不使用自定义比较器,我会在集合中得到四个元素,因为 :zip 字段是不同的。

(clojure.set/union set-a set-b)

#{{:id 3, :name "XYZ", :zip 78704} {:id 1, :name "ABC", :zip 78753}
  {:id 1, :name "ABC", :zip 78759} {:id 2, :name "DEF", :zip 78759}}

使用自定义比较器或比较在两组之间找到联合的惯用方法是什么?

4

2 回答 2

3

您可以使用它group-by来执行此操作:

(map first (vals (group-by (juxt :id :name) (concat set-a set-b))))

或螺纹:

(->> (concat set-a set-b)
     (group-by (juxt :id :name))
     (vals)
     (map first))

这是通过组合键/值对元素进行分组,即(juxt :id :name). 然后它抓取生成的地图的ues val,然后遍历它以获取每个分组中的第一项。mapfirst

或者使用一些专门为此构建的代码,例如distinct-by.

请注意,这些方法适用于任何集合,而不仅仅是集合。

于 2018-01-20T23:35:14.837 回答
1

如果您不介意完全扔掉 :zip,请考虑使用 clojure.set/project。

(clojure.set/union
 (clojure.set/project set-a [:id :name])
 (clojure.set/project set-b [:id :name]))

#{{:id 3, :name "XYZ"} {:id 2, :name "DEF"} {:id 1, :name "ABC"}}
于 2018-01-21T00:07:11.863 回答