Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion 在clojure中实现两个集合之间的XOR_Recursion_Clojure_Functional Programming - Fatal编程技术网

Recursion 在clojure中实现两个集合之间的XOR

Recursion 在clojure中实现两个集合之间的XOR,recursion,clojure,functional-programming,Recursion,Clojure,Functional Programming,我正在努力学习Clojure,我是个新手。我正在尝试实现两个集合之间集合差的递归版本 我试图做的是首先合并两个列表,将组合转换为一个集合以删除重复项,然后将混乱传递回其自身,并检查组合集合的第一个元素是否在两个输入列表中。如果是,请将组合集合的其余部分与原始集合一起传递回,并重复此过程。。。但它总是返回一个空列表。我不认为代码有那么好。我不熟悉函数式编程 也许我使用的逻辑和正确性不高?我做了一个测试,普通榆树一开始并不是空的,但它可能会提前返回,并有一个空的列表?任何帮助都将不胜感激。谢谢 (d

我正在努力学习Clojure,我是个新手。我正在尝试实现两个集合之间集合差的递归版本

我试图做的是首先合并两个列表,将组合转换为一个集合以删除重复项,然后将混乱传递回其自身,并检查组合集合的第一个元素是否在两个输入列表中。如果是,请将组合集合的其余部分与原始集合一起传递回,并重复此过程。。。但它总是返回一个空列表。我不认为代码有那么好。我不熟悉函数式编程

也许我使用的逻辑和正确性不高?我做了一个测试,普通榆树一开始并不是空的,但它可能会提前返回,并有一个空的列表?任何帮助都将不胜感激。谢谢

(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> 
  • 您必须知道
    包含?
    仅适用于关联集合,如地图或向量(向量是键为索引的关联集合)。见问题。 for
    some
    提供了在任何类型的集合中测试(如果它包含给定元素)的惯用方法

  • 在没有找到公共元素的情况下(
    :else
    ),您忘记了将元素连接到
    返回列表中

  • 注意:这种风格比Clojurian风格更为利索;要保留基于递归的解决方案,可以使用
    循环/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> 
    
  • 您必须知道
    包含?
    仅适用于关联集合,如地图或向量(向量是键为索引的关联集合)。见问题。 for
    some
    提供了在任何类型的集合中测试(如果它包含给定元素)的惯用方法

  • 在没有找到公共元素的情况下(
    :else
    ),您忘记了将元素连接到
    返回列表中

  • 注意:这种风格比Clojurian风格更为利索;要保留基于递归的解决方案,可以使用
    循环/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