【问题标题】:NOT - EXISTS / NOT - IN type query in ClojureNOT - EXISTS / NOT - Clojure 中的 IN 类型查询
【发布时间】:2011-09-03 00:43:02
【问题描述】:

我有 2 个如下数据结构

(ns test)

(def l 
  [{:name "Sean" :age 27} 
   {:name "Ross" :age 27}
   {:name "Brian" :age 22}])

(def r 
  [{:owner "Sean" :item "Beer" }
   {:owner "Sean" :item "Pizza"}
   {:owner "Ross" :item "Computer"} 
   {:owner "Matt" :item "Bike"}])

我想找不拥有任何物品的人。 (布赖恩在这种情况下所以 [ {:name "Brian" :age 22}] 如果这是 SQL,我会做左外连接或不存在,但我不确定如何在 clojure 中以更高效的方式执行此操作。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    虽然 Chuck 的解决方案无疑是最明智的解决方案,但我发现可以使用 clojure.set 根据关系代数运算符编写解决方案很有趣:

    (require '[clojure.set :as set])
    (set/difference (set l)
                    (set/project (set/join r l {:owner :name})
                                 #{:name :age}))
    ; => #{{:name "Brian", :age 22}}
    

    【讨论】:

      【解决方案2】:

      您基本上想在l 上做一个filter,但是否定的。我们可以只使用not 条件,但remove 函数已经为我们完成了这项工作。所以像:

      (let [owner-names (set (map :owner r))]
        (remove #(owner-names (% :name)) l))
      

      (我认为它与集合一起阅读会更好,但如果您想避免分配集合,您可以使用(remove (fn [person] (some #(= (% :owner) (person :name)) r)) l)。)

      【讨论】:

      • 我同意它看起来更好,但我会将其压缩为(remove (comp (set (map :owner r)) :name) l)
      • 另外,在r 的重复线性扫描中,分配集合可以为您节省大量时间。
      猜你喜欢
      • 2015-07-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 2016-07-22
      • 2016-02-11
      • 2014-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多