使用clojure返回一个元素和两个原始序列不相同的序列
我有两个序列,可以是向量或列表。现在我想返回一个序列,其元素与这两个序列不相同 以下是一个例子:使用clojure返回一个元素和两个原始序列不相同的序列,clojure,tail-recursion,Clojure,Tail Recursion,我有两个序列,可以是向量或列表。现在我想返回一个序列,其元素与这两个序列不相同 以下是一个例子: (removedupl [1 2 3 4] [2 4 5 6]) = [1 3 5 6] (removeddpl [] [1 2 3 4]) = [1 2 3 4] 我现在很困惑。这是我的代码: (defn remove-dupl [seq1 seq2] (loop [a seq1 b seq2] (if (not= (first a) (first b))
(removedupl [1 2 3 4] [2 4 5 6]) = [1 3 5 6]
(removeddpl [] [1 2 3 4]) = [1 2 3 4]
我现在很困惑。这是我的代码:
(defn remove-dupl [seq1 seq2]
(loop [a seq1 b seq2]
(if (not= (first a) (first b))
(recur a (rest b)))))
但我不知道下一步该怎么办。我对Clojure还是新手,但我认为功能思维更倾向于编写函数,而不是“手工”编写,因此我提出以下解决方案:
(defn remove-dupl [seq1 seq2]
(concat
(remove #(some #{%} seq1) seq2)
(remove #(some #{%} seq2) seq1)))
编辑:我认为最好将删除部分定义为一个本地函数并重用它:
(defn remove-dupl [seq1 seq2]
(let [removing (fn [x y] (remove #(some #{%} x) y))]
(concat (removing seq1 seq2) (removing seq2 seq1))))
编辑2:正如蒂莫西普拉特利所评论的那样
(defn remove-dupl [seq1 seq2]
(let [removing (fn [x y] (remove (set x) y))]
(concat (removing seq1 seq2) (removing seq2 seq1))))
我鼓励你们从集合运算的角度来考虑这个问题
(defn extrasection [& ss]
(clojure.set/difference
(apply clojure.set/union ss)
(apply clojure.set/intersection ss)))
这种公式假设输入是集合
(extrasection #{1 2 3 4} #{2 4 5 6})
=> #{1 6 3 5}
通过对列表、序列或向量调用(set…)函数可以轻松实现
即使您更喜欢使用面向序列的解决方案,请记住,如果您扫描两个序列[除非它们已排序],搜索两个序列也是一项O(n*n)任务。集合可以在一次过程中构造,查找速度非常快。检查重复项是一项使用set的O(nlogn)任务。您的代码有几个问题
- 它不测试两个序列参数的结尾
- 它通过
b
,但不通过a
李>
- 当任意两个序列具有相同的值时,它隐式返回
nil
第一个要素
您希望从连接的序列中删除公共元素。您必须首先计算出公共元素,否则您不知道删除什么。所以
我们使用
clojure.set/intersection
查找公共元素
concat
将集合缝合在一起
remove
从(2)中删除(1)
vec
转换为向量
因此
。。。给
(removedupl [1 2 3 4] [2 4 5 6]) ; [1 3 5 6]
(removedupl [] [1 2 3 4]) ; [1 2 3 4]
。。。根据需要 对!!使用let后,阅读代码更容易。由于我是新学员,请您详细解释一下这句话(删除#(some#{%}x)y)。我查阅了参考资料,但对此我一无所知。非常感谢你!(remove(set seq1)seq2)比O(n^2)更快O(nlogn)而不是O(n^2)@Timothyprattley感谢您的更正,将进行更新。@xuifenxu Check@xuifenxu关于#()符号,请检查好的。我在查看交叉点,但记不起它的名称。如果两个输入序列都像示例中那样排序,则可以在O(n)时间内完成,而不需要集合。否则,集合就是方法。输入总是像示例中那样排序,还是只是巧合?
(removedupl [1 2 3 4] [2 4 5 6]) ; [1 3 5 6]
(removedupl [] [1 2 3 4]) ; [1 2 3 4]