外部加入Clojure

时间:2012-10-22 10:54:27

标签: clojure outer-join

与此问题类似:Inner-join in clojure

是否有任何Clojure库中的地图集合执行外连接(左,右和完全)功能?

我想这可以通过修改clojure.set/join的代码来完成,但这似乎是一个常见的要求,所以检查它是否已经存在是值得的。

这样的事情:

(def s1 #{{:a 1, :b 2, :c 3}
          {:a 2, :b 2}})

(def s2 #{{:a 2, :b 3, :c 5}
          {:a 3, :b 8}})


;=> (full-join s1 s2 {:a :a})
;
;   #{{:a 1, :b 2, :c 3}
;     {:a 2, :b 3, :c 5}
;     {:a 3, :b 8}}

左右外连接的相应函数,即包括左侧,右侧或两侧的连接键没有值(或nil值)的条目。

1 个答案:

答案 0 :(得分:5)

Sean Devlin(Full Disclojure成名)table-utils有以下联接类型:

  • 内加入
  • 左外联接
  • 右外联接
  • 全外联接
  • 自然联接
  • 交叉联接

它暂时没有更新,但工作在1.3,1.4和1.5。为了使它在没有任何外部依赖性的情况下工作:

  • fn-tuple替换为juxt
  • 使用(:use )
  • 替换ns声明中的整个(require [clojure.set :refer [intersection union]])子句
  • 从下面添加函数map-vals:

或者

(defn map-vals
  [f coll]
  (into {} (map (fn [[k v]] {k (f v)}) coll)))

或Clojure 1.5及以上

(defn map-vals
  [f coll]
  (reduce-kv (fn [acc k v] (assoc acc k (f v))) {} coll))

库的用法是连接类型,两个集合(两组映射,如上例,或两个sql结果集)和至少一个连接fn。由于关键字是地图上的函数,通常只有连接键才足够:

=> (full-outer-join s1 s2 :a :a)
   ({:a 1, :c 3, :b 2}
    {:a 2, :c 5, :b 3}
    {:b 8, :a 3})

如果我没记错,Sean试图在不久前将table-utils用于contrib,但这种情况从未解决过。太糟糕了,它从来没有得到它自己的项目(在github / clojars上)。在Stackoverflow或Clojure Google小组中,会不时出现像这样的库的问题。

另一种选择可能是使用datomic中的数据记录库来查询clojure数据结构。 Stuart Halloway在他的要点中some examples