在clojure中重复删除一个序列

时间:2012-06-07 11:21:55

标签: clojure

我需要定义一个函数,它接受一个序列和一些作用于序列内元素的函数。它返回旧序列中的序列,其中删除了具有重复函数值的元素。

(defn dedup [seq & functions] ...)

例如,如果

(f1 1) = 'a'
(f1 2) = 'a'
(f1 3) = 'c'
(f1 4) = 'd'

(f2 1) = 'za'
(f2 2) = 'zb'
(f2 3) = 'zc'
(f2 4) = 'zb'

然后

(dedup [1 2 3 4] f1 f2) 

返回(1 3)

的序列

我该怎么做?

编辑: 编辑了测试值,以免造成误解

编辑: 以下是仅有1个函数

的情况的(不那么实用的)实现
(defn dedup [seq f]
  (loop [values #{} seq1 seq seq2 '()]
    (let [s (first seq1)]
      (if (nil? s)
        (reverse seq2)
        (let [v (f s)]
          (if (contains? values v)
            (recur values (rest seq1) seq2)
            (recur (conj values v) (rest seq1) (conj seq2 s))))))))

1 个答案:

答案 0 :(得分:3)

你的例子似乎与文本相矛盾 - 它返回两个函数一致的值。

(defn dedup [seq & fns]
  (for [s seq :when (apply = (map #(% s) fns))] s))

(dedup [1 2 3 4] 
  #(case % 1 "a" 2 "a" 3 "c" 4 "d") 
  #(case % 1 "a" 2 "b" 3 "c" 4 "b"))
(1 3)

也许这有点太紧凑了? #(... % ...)相当于(fn [x] (... x ...)),而map中的dup会在函数上运行,并将它们全部应用于序列中的相同值。

你也可以用

进行测试
(dedup [1 2 3 4] {1 "a" 2 "a" 3 "c" 4 "d"} {1 "a" 2 "b" 3 "c" 4 "b"})
(1 3)
我认为也许混淆超过了英语的含义。 “重复”表示重复一个值。所以“a”“a”是“a”的副本。我怀疑你的意思是“多重” - 你想删除你获得多个(不同)值的条目。

pps你也可以使用filter

(defn dedup [seq & fns] 
  (filter #(apply = (map (fn [f] (f %)) fns)) seq))

我需要明确写一个匿名函数,因为你无法嵌套#(...)