从两个序列中删除重复元素

时间:2016-05-08 21:36:39

标签: clojure

我想知道如何从两个序列中删除重复元素并组合两个序列。例如,

user=>(remove-dup [1 4 7 10 16] [2 7 18 4])
(1 2 10 18 16)

我的代码是:

(defn remove-dup [l1 l2]
  (let [list (concat l1 l2)]
    (loop [l list res '()]
        (if (>= (second (first (frequencies l))) 2) 
            (recur (rest l) res)
            (recur (rest l) (conj res (first (first l))))))))

但是当我运行代码时,我收到了错误消息:

IllegalArgumentException Don't know how to create ISeq from: java.lang.Long  clojure.lang.RT.seqFrom (RT.java:528)

如何修复此代码。谢谢!

5 个答案:

答案 0 :(得分:6)

您的错误在这里:

int *shiftArray(int *, int, int);

int main()
{
    int size = 6;
    int *b = new int[size]{ 1, 2, 3, 4, 5, 6 };

    int shiftStartIndex = 3;

    b = shiftArray(b, size, shiftStartIndex);

    int newSize = size - shiftStartIndex;

    for (int i = 0; i < newSize; i++)
    {
        cout << b[i] << " ";
    }

    cin.ignore();
    return 0;
}

int *shiftArray(int *arr, int size, int stIndex)
{
    int *a = new int[size - stIndex];

    for (int i = 0; i < size - stIndex; i++)
    {
        a[i] = arr[i + stIndex];
    }

    delete[] arr;

    return a;
}

请记住,(first (first l)) 是您尚未处理的所有元素的序列。例如,在l的第一次迭代中,loop可能如下所示:

l

您可以从中看到(1 4 7 10 16 2 7 18 4) 将是(first l),因此1会尝试将数字视为序列,但这不起作用。

如果您仅使用(first (first l))替换(first (first l)),您将获得(first l),因为您没有基本情况:NullPointerException是什么时候应该做的?空?你可能会这样做(l是你当前,,,表达式的占位符):

if

但是,如果我们现在尝试使用该方法,我们仍然无法获得正确的结果:

(if (empty? l)
  res
  ,,,)

槽糕。

我可以尝试更多地使用您的代码来使其工作,但是有更好的方法来解决这个问题。由于您尝试删除重复项并且不关心订单,因此clojure.set中的函数是此作业的正确工具。我会像这样写(remove-dup [1 4 7 10 16] [2 7 18 4]) ;=> (4 18 7 2 16 10 1)

remove-dup

示例:

(require '[clojure.set :as set])

(defn remove-dup [c1 c2]
  (let [[s1 s2] (map set [c1 c2])]
    (seq (set/difference (set/union s1 s2) (set/intersection s1 s2)))))

答案 1 :(得分:2)

您的代码中存在许多致命错误:

打破它的东西是(first (first l)),因为l是数字列表,当你尝试取第一项数字时它会引发错误。

但还有更重要的一些:

首先,即使你的代码是正确的,它也没有任何破坏循环的情况,所以它可能会导致无限循环(或某种异常)。其次是你对frequencies用法的完全误解。您不能依赖frequencies结果的顺序,因为它返回无序映射(更不用说它是在每次循环迭代中调用的,这对于性能非常糟糕)。

这就是我如何通过循环中的集合传递来做这样的事情:

(defn unique [coll1 coll2]
  (let [items (concat coll1 coll2)]
    (loop [res #{}
           seen #{}
           [x & xs :as items] items]
      (cond ;; if there are no items left to check, returning result
            (empty? items) res
            ;; if we've already seen the first item of a coll, remove it from the resulting set
            (seen x) (recur (disj res x) seen xs)
            ;; otherwise mark it as seen, and add it to the result set
            :else (recur (conj res x) (conj seen x) xs)))))

在repl中:

user> (unique [1 4 7 10 16] [2 7 18 4])
#{1 2 16 10 18}

答案 2 :(得分:0)

(defn remove-dupl [l1 l2]
  (let [rmdup (fn [l1 l2] (remove (set l1) l2))]
    (concat (rmdup l1 l2) (rmdup l2 l1))))

答案 3 :(得分:0)

试试这个解决方案

(defn remove-dup [l1 l2]
  (let [ls (concat l1 l2)]
    (loop [l (frequencies ls) res '()]
        (if (empty? l) res
            (if (>= (second (first l)) 2) 
                (recur (rest l) res)
                (recur (rest l) (cons (first (first l)) res)))))))

答案 4 :(得分:0)

其他人发现了您的错误。我想看看你想做什么。

鉴于此

  • 订单并不重要
  • 您要删除重复的元素

这是设置操作 exclusive or(XOR)。

它不包含在clojure.set中。正如Sam Estep所做的那样,我们可以根据我们的操作来定义它,或者自己更直接地写它:

(defn exclusive-or [sa sb]
  (if (<= (count sa) (count sb))
    (reduce
     (fn [ans a]
       (if (contains? sb a)
         (disj ans a)
         (conj ans a)))
     sb
     sa)
    (recur sb sa)))

然后我们可以定义

(defn remove-dup [xs ys]dited 
  (exclusive-or (set xs) (set ys))

例如,

(remove-dup [1 4 7 10 16] [2 7 18 4]) ;#{1 2 10 16 18}

修改exclusive-or中的错误。