你做了几个错误:
- 你在序列中使用
contains?
。它仅适用于关联 集合。改为使用some
。
- 对于
empty?
,您已经测试了序列的第一个元素(head
)。 测试整个序列。
- 使用向量来积累答案。
conj
将元素添加到列表的前面 ,颠倒了答案。
纠正这些,我们得到
(defn cut-at-repetition [a-seq]
(loop [[head & tail :as all] a-seq, coll []]
(if (empty? all)
coll
(if (some #(= head %) coll)
coll
(recur tail (conj coll head))))))
(cut-at-repetition [1 2 3 1 4])
=> [1 2 3]
以上的作品,但它是缓慢的,因为它会扫描所有的元素缺席整个序列。所以最好使用一套。
我们称之为功能take-distinct
,因为它与take-while
类似。如果我们遵循的先例,并使其懒惰,我们可以这样做:
(defn take-distinct [coll]
(letfn [(td [seen unseen]
(lazy-seq
(when-let [[x & xs] (seq unseen)]
(when-not (contains? seen x)
(cons x (td (conj seen x) xs))))))]
(td #{} coll)))
我们得到了有限序列的预计业绩:
(map (juxt identity take-distinct) [[] (range 5) [2 3 2]]
=> ([[] nil] [(0 1 2 3 4) (0 1 2 3 4)] [[2 3 2] (2 3)])
我们可以拿那么多,我们从需要无尽的结果:
(take 10 (take-distinct (range)))
=> (0 1 2 3 4 5 6 7 8 9)
我会打电话给你的渴望版本take-distinctv
,在map
- >mapv
先例。我会做这样说:
(defn take-distinctv [coll]
(loop [seen-vec [], seen-set #{}, unseen coll]
(if-let [[x & xs] (seq unseen)]
(if (contains? seen-set x)
seen-vec
(recur (conj seen-vec x) (conj seen-set x) xs))
seen-vec)))
请注意,我们携带看到元素两次:
- 作为载体,返回的解决方案;和
- 作为一个集合,以测试成员身份。
三个失误的两个是由@cfrick评论。
'包含?'检查,如果钥匙在例如,一套或地图。它也可以用于数组/向量来检查_index_是否存在。它在seqs上不受支持。如果列表是空的,'head'还有'a-seq'(第一个)的值,而'empty?'用于检查。 – cfrick