Clojure 更好的序列重复消除器

Clojure 更好的序列重复消除器,clojure,Clojure,我使用此函数来删除连续的重复项,但我想知道是否有更好或更短的方法来使用distinct或类似的东西来表达它 (defn duplicates [s] (reduce #(if-not (= (last %1) %2) (conj %1 %2) %1) [] s)) reduce中的匿名函数将一个元素连接成一个序列(如果它与最后一个元素不同)。你可以这样重写它: (defn maybe-conj [s e] (if (= (last s) e)

我使用此函数来删除连续的重复项,但我想知道是否有更好或更短的方法来使用
distinct
或类似的东西来表达它

(defn duplicates
  [s]
  (reduce 
    #(if-not (= (last %1) %2) 
      (conj %1 %2) %1) 
    [] s))

reduce中的匿名函数将一个元素连接成一个序列(如果它与最后一个元素不同)。你可以这样重写它:

(defn maybe-conj [s e]
  (if (= (last s) e)
     s
     (conj s e)))
然后您可以将
压缩序列重写为:

(defn compress-sequence [s]
  (reduce maybe-conj [] s))
这将要做的是遍历序列的每个元素,并且仅当它与当前向量中的最后一个元素不同时才将其附加到初始空向量。输出将是初始序列的向量,删除任何运行。例如:

(压缩序列[1 1 1 1 2 3 4 5 5 5 6 6 6 6 6 7 8 9])

评估为


[1 2 3 4 5 6 5 6 7 8 9]
clojure-1.7.0-alpha1
在名称下有此函数的正确版本

您引用的一个返回其输入序列,没有连续的重复项。(几乎可以肯定)如果输入序列开始,它也会不知不觉地吞下所有连续的
nil

#(if-not (= (last %1) %2)
    (conj %1 %2)
    %1)
要减少的lambda表示:如果累加器的最后一个元素(
%1
)与下一个输入元素(
%2
)不相等,则将其添加到累加器中,否则返回累加器

由于
(last[])
的计算结果为
nil
,因此当累加器为空时,它将永远不会添加
nil
值。我将此作为练习留给读者:

确保重复的
返回输入
[nil-nil-true-nil]
的预期结果
[nil-nil-true-nil]

注意:使用向量操作时,使用
peek
的性能明显优于
last

EDIT(因为您编辑了问题):
distinct
只返回输入序列的每个值一次。与
set
不同,它返回惰性序列

A.Webb以注释的形式发布了一种更为惯用的方法来编写
副本
/
重复数据消除
(因为它也是懒惰的)。否则,将lambda修复为在空累加器作为输入的情况下正确工作,并使用
peek
而不是
last
将更为惯用

clojure-1.7.0-alpha1
中,您将使用
重复数据消除
传感器进行即时评估,而不是固定lambda。g、 :

(into [] (dedupe) [nil nil true true nil])
-> [nil true nil] 
或用于延迟评估:

(dedupe [nil nil true true nil])
-> (nil true nil)

嗯,“我很难理解这个函数做什么”,但是你正确地标记了这个问题^ ^ ^更惯用的方式来表达这个
(defn compress[s](map first(partition by identity s))
@A.Webb当第一个元素为nil时,你的实现表现不同。@leograpenthin是,正确:)。要删除所有重复值还是仅删除连续值?按照fn的编写方式,
(重复[1 2 1])
返回
[1 2 1]