【问题标题】:Clojure: how to use compare with set/union [duplicate]Clojure:如何使用与 set/union 进行比较 [重复]
【发布时间】:2018-06-29 22:16:27
【问题描述】:

为了举例,假设我有两组:

(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}}

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

【问题讨论】:

    标签: clojure set compare comparator set-union


    【解决方案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"}}
    

    【讨论】:

    • 感谢您回答问题。我的问题应该更具体一些,我也需要 :zip 。不过,我确实从你那里学到了一些关于 clojure.set/project 的新东西。
    【解决方案2】:

    您可以使用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))对元素进行分组。然后它抓取生成的地图的values,然后通过maps first 获取每个分组中的第一项。

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

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

    【讨论】:

    • 感谢您回答问题。我太担心通过联合解决问题,以至于我错过了这个不经意的解决方案。
    猜你喜欢
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多