且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

更好的序列重复卸妆

更新时间:2022-10-15 12:20:40

clojure-1.7.0-alpha1 具有此函数的正确版本,名称 重复数据删除



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

 #(if(not(=(last%1)%2)
(conj%1%2)
%1)

lambda减少说:如果累加器的最后一个元素(%1 )不等于下一个输入元素(%2 ),将其添加到累加器,否则返回累加器。



因为(last [])计算为 nil 当累加器为空时,它不会添加 nil 值。我将这个练习作为练习留给读者:



确保重复返回预期结果 [nil true nil] for input [nil nil true true nil] b
$ b

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



EDIT (由于您编辑了您的问题): distinct 的输入序列只有一次。与 set 不同,它返回lazy-sequence。



一种更惯用的方式来写重复 / 重复数据删除是A. Webb发布为评论(因为它也是懒惰)。否则,使用空累加器作为其输入,并使用 peek 而不是最后



不是固定lambda, clojure-1.7.0-alpha1 c $ c> dedupe 传感器,用于急切评估,e。 g。:

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

或者为了延迟评估:


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


I made this function to remove consecutive duplicates, but I wanted to know if there was a better or shorter way to express it using distinct or something like that.

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

clojure-1.7.0-alpha1 has a correct version of this function under the name dedupe.

The one you quoted returns its input sequence without consecutive duplicates. (Almost certainly) unwittingly, it also swallows all successive nil values if they begin the input sequence.

#(if-not (= (last %1) %2)
    (conj %1 %2)
    %1)

The lambda to reduce says: If the last element of the accumulator (%1) is unequal to the next input element (%2), add it to the accumulator, otherwise return the accumulator.

Because (last []) evaluates to nil it will never add nil values while the accumulator is empty. I leave fixing that as an exercise to the reader:

Make sure that duplicates returns the expected result [nil true nil] for input [nil nil true true nil].

Note: When operating with a vector, using peek performs significantly better than last.

EDIT (Since you edited your question): distinct returns each value of the input sequence only once. Unlike set it returns lazy-sequence.

A more idiomatic way to write duplicates/dedupe is the one that A. Webb posted as a comment (since it is also lazy). Otherwise, fixing the lambda to work correctly with an empty accumulator as its input and using peek instead of last would be more idiomatic.

Instead of fixing the lambda, in clojure-1.7.0-alpha1 you would use the dedupe transducer for eager evaluation, e. g.:

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

Or for lazy evaluation:

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