Clojure 中的外部联接
Posted
技术标签:
【中文标题】Clojure 中的外部联接【英文标题】:Outer join in Clojure 【发布时间】:2012-10-12 04:11:37 【问题描述】:类似这个问题: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】:Sean Devlin(Full Disclojure 成名)table-utils 具有以下联接类型:
内连接 左外连接 右外连接 完全外连接 自然连接 交叉连接它已经有一段时间没有更新了,但可以在 1.3、1.4 和 1.5 中使用。让它在没有任何外部依赖的情况下工作:
将fn-tuple
替换为juxt
将 ns 声明中的整个 (:use )
子句替换为 (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))
库的使用是join类型,两个集合(如上例的两组map,或者两个sql结果集)和至少一个join 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 上)。 *** 或 Clojure Google 小组中时不时会出现有关此类库的问题。
另一个选项可能是使用来自 datomic 的数据日志库来查询 clojure 数据结构。 Stuart Halloway 在他的要点中有some examples。
【讨论】:
虽然我最初不愿意复制和粘贴代码,但这是我最终解决问题的方法。谢谢! 我也有同样的犹豫,但是有 SQL 背景,这些抽象自然而然,所以最后我屈服了。也许我会尝试自己写一个这样的库并推动它到 Clojars,但我对 github 和开源的东西不是很熟悉.. 我尝试使用 Clojure 1.6,在上述建议的修复之后,它适用于上面的示例,但是我有 2 个表的堆栈溢出错误,每个表大约有 4,000 行。这是错误:“java.lang.***Error:null”。我已经用 :jvm-opts ["-Xmx1024m"] 设置了我的项目,请提出任何简单的修复或替代方案。谢谢! 源码中join-worker的实现中将“reduce concat”替换为“apply concat”可以解决栈溢出问题。以上是关于Clojure 中的外部联接的主要内容,如果未能解决你的问题,请参考以下文章