Recursion 在clojure中实现两个集合之间的XOR
我正在努力学习Clojure,我是个新手。我正在尝试实现两个集合之间集合差的递归版本 我试图做的是首先合并两个列表,将组合转换为一个集合以删除重复项,然后将混乱传递回其自身,并检查组合集合的第一个元素是否在两个输入列表中。如果是,请将组合集合的其余部分与原始集合一起传递回,并重复此过程。。。但它总是返回一个空列表。我不认为代码有那么好。我不熟悉函数式编程 也许我使用的逻辑和正确性不高?我做了一个测试,普通榆树一开始并不是空的,但它可能会提前返回,并有一个空的列表?任何帮助都将不胜感激。谢谢Recursion 在clojure中实现两个集合之间的XOR,recursion,clojure,functional-programming,Recursion,Clojure,Functional Programming,我正在努力学习Clojure,我是个新手。我正在尝试实现两个集合之间集合差的递归版本 我试图做的是首先合并两个列表,将组合转换为一个集合以删除重复项,然后将混乱传递回其自身,并检查组合集合的第一个元素是否在两个输入列表中。如果是,请将组合集合的其余部分与原始集合一起传递回,并重复此过程。。。但它总是返回一个空列表。我不认为代码有那么好。我不熟悉函数式编程 也许我使用的逻辑和正确性不高?我做了一个测试,普通榆树一开始并不是空的,但它可能会提前返回,并有一个空的列表?任何帮助都将不胜感激。谢谢 (d
(defn alone
([l1 l2]
(cond (empty? l1) l2
(empty? l2) l1
:else (alone (vec (set (into l1 l2))) '() l1 l2)))
([common-elms return-list l1 l2]
"common-elms = set of common elements
return-list = list of XOR items
l1 = list 1
l2 = list 2 "
(cond (empty? common-elms) return-list
(and (contains? (first common-elms) l1) (contains? (first common-elms) l2))
(alone (rest common-elms) return-list l1 l2)
:else (alone (rest common-elms) return-list l1 l2))))
您尝试递归地这样做有什么原因吗?如果这不是要求,请使用
clojure.set
命名空间:
(defn xor-list [l1 l2]
(let [s1 (set l1)
s2 (set l2)
i (clojure.set/intersection s1 s2)]
(seq (clojure.set/union
(clojure.set/difference s1 i)
(clojure.set/difference s2 i)))))
(defn xor-list [l1 l2]
(let [s1 (set l1)
s2 (set l2)]
(seq (clojure.set/difference
(clojure.set/union s1 s2)
(clojure.set/intersection s1 s2)))))
您尝试递归地这样做有什么原因吗?如果这不是要求,请使用
clojure.set
命名空间:
(defn xor-list [l1 l2]
(let [s1 (set l1)
s2 (set l2)
i (clojure.set/intersection s1 s2)]
(seq (clojure.set/union
(clojure.set/difference s1 i)
(clojure.set/difference s2 i)))))
(defn xor-list [l1 l2]
(let [s1 (set l1)
s2 (set l2)]
(seq (clojure.set/difference
(clojure.set/union s1 s2)
(clojure.set/intersection s1 s2)))))
或者更简单,使用
clojure.set
名称空间:
(defn xor-list [l1 l2]
(let [s1 (set l1)
s2 (set l2)
i (clojure.set/intersection s1 s2)]
(seq (clojure.set/union
(clojure.set/difference s1 i)
(clojure.set/difference s2 i)))))
(defn xor-list [l1 l2]
(let [s1 (set l1)
s2 (set l2)]
(seq (clojure.set/difference
(clojure.set/union s1 s2)
(clojure.set/intersection s1 s2)))))
但它只是返回列表的两个参数的函数。对于返回集合的任意数目的集合,对于一般情况下的
clojure.set/xor
如clojure.set/intersection
,这应该得到增强。或者更简单,使用clojure.set
命名空间:
(defn xor-list [l1 l2]
(let [s1 (set l1)
s2 (set l2)
i (clojure.set/intersection s1 s2)]
(seq (clojure.set/union
(clojure.set/difference s1 i)
(clojure.set/difference s2 i)))))
(defn xor-list [l1 l2]
(let [s1 (set l1)
s2 (set l2)]
(seq (clojure.set/difference
(clojure.set/union s1 s2)
(clojure.set/intersection s1 s2)))))
但它只是返回列表的两个参数的函数。对于任何数量的集返回一个集,对于一般情况下的
clojure.set/xor
如clojure.set/intersection
,这应该得到增强。首先,@ivanpierre解决方案当然是最好的,因为它实际上使用了clojure.set
的第一个属性并利用了它。但是您自己的基于递归的解决方案是有效的,尽管代码中存在一些缺陷。修改版本如下,并附有说明:
(defn alone
([l1 l2]
(cond (empty? l1) l2
(empty? l2) l1
:else (alone (vec (set (into l1 l2))) '() l1 l2)))
([common-elms return-list l1 l2]
"common-elms = set of common elements
return-list = list of XOR items
l1 = list 1
l2 = list 2 "
(cond (empty? common-elms) return-list
(let [ce (first common-elms)] ;; see [1]
(and (some #{ce} l1)
(some #{ce} l2)))
(alone (rest common-elms)
return-list
l1 l2)
:else (alone (rest common-elms)
(conj return-list (first common-elms)) ;; see [2]
l1 l2))))
user> (alone '(1 2 3 4 5) '(3 4 5 6 7))
(2 6 1 7)
user>
包含?
仅适用于关联集合,如地图或向量(向量是键为索引的关联集合)。见问题。
forsome
提供了在任何类型的集合中测试(如果它包含给定元素)的惯用方法:else
),您忘记了将元素连接到返回列表中
循环/recur
。以下是N个列表的一般解决方案:
(defn xor
([l1 l2]
(loop [l1 (set l1)
l2 (set l2)
xor '()]
(if (seq l1)
(let [e (first l1)]
(if (l2 e) ;; l2 is a set, test if e is in l2
(recur (rest l1) (disj l2 e) xor)
(recur (rest l1) l2 (conj xor e))))
(reduce conj xor l2)))) ;; when l1 is empty, add all element left in l2
([l1 l2 & more]
(reduce xor (xor l1 l2) more)))
user> (let [l1 '(1 1 2 3 4 5)
l2 '(3 4 5 5 6 7)
l3 '(1 10 11 13)
l4 '(1 2 11 6 6)]
(println (xor l1 l2 l3 l4)))
(1 10 13 7)
nil
首先,@ivanpierre解决方案当然是最好的,因为它实际上使用了的第一个属性并利用了
clojure.set
。但是您自己的基于递归的解决方案是有效的,尽管代码中存在一些缺陷。修改版本如下,并附有说明:
(defn alone
([l1 l2]
(cond (empty? l1) l2
(empty? l2) l1
:else (alone (vec (set (into l1 l2))) '() l1 l2)))
([common-elms return-list l1 l2]
"common-elms = set of common elements
return-list = list of XOR items
l1 = list 1
l2 = list 2 "
(cond (empty? common-elms) return-list
(let [ce (first common-elms)] ;; see [1]
(and (some #{ce} l1)
(some #{ce} l2)))
(alone (rest common-elms)
return-list
l1 l2)
:else (alone (rest common-elms)
(conj return-list (first common-elms)) ;; see [2]
l1 l2))))
user> (alone '(1 2 3 4 5) '(3 4 5 6 7))
(2 6 1 7)
user>
包含?
仅适用于关联集合,如地图或向量(向量是键为索引的关联集合)。见问题。
forsome
提供了在任何类型的集合中测试(如果它包含给定元素)的惯用方法:else
),您忘记了将元素连接到返回列表中
循环/recur
。以下是N个列表的一般解决方案:
(defn xor
([l1 l2]
(loop [l1 (set l1)
l2 (set l2)
xor '()]
(if (seq l1)
(let [e (first l1)]
(if (l2 e) ;; l2 is a set, test if e is in l2
(recur (rest l1) (disj l2 e) xor)
(recur (rest l1) l2 (conj xor e))))
(reduce conj xor l2)))) ;; when l1 is empty, add all element left in l2
([l1 l2 & more]
(reduce xor (xor l1 l2) more)))
user> (let [l1 '(1 1 2 3 4 5)
l2 '(3 4 5 5 6 7)
l3 '(1 10 11 13)
l4 '(1 2 11 6 6)]
(println (xor l1 l2 l3 l4)))
(1 10 13 7)
nil