Sie haben gemacht mehrere Fehler:
- Sie
contains?
auf einer Sequenz benutzt habe. Es funktioniert nur auf assoziativen Sammlungen. Verwenden Sie stattdessen some
. Sie haben das erste Element der Sequenz (head
) für empty?
getestet. Testen Sie die gesamte Sequenz.
- Verwenden Sie einen Vektor, um die Antwort zu akkumulieren.
conj
fügt Elemente zu der Vorderseite einer Liste hinzu und kehrt die Antwort um.
diese Korrektur, erhalten wir
(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]
Die oben genannten Arbeiten, aber es ist langsam, da es die gesamte Sequenz für jedes fehlende Element abtastet. Also besser ein Set verwenden.
Nennen wir die Funktion take-distinct
, da es take-while
ähnlich ist. Wenn wir diesen Präzedenzfall und machen es faul folgen, können wir es tun so:
(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)))
Wir die erwarteten Ergebnisse für die Finite-Sequenzen erhalten:
(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)])
Und wir können so viel nehmen, wie wir von einem benötigen endlose Folge: ->mapv
Präzedenzfall
(take 10 (take-distinct (range)))
=> (0 1 2 3 4 5 6 7 8 9)
würde ich Ihre eifrige Version take-distinctv
, auf dem map
nennen. Und ich würde es auf diese Weise tun:
(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)))
Beachten Sie, dass wir die gesehenen Elemente zweimal tragen:
- als Vektor, als die Lösung zurückzukehren; und
- als Set, um die Mitgliedschaft von zu testen.
Zwei der drei Fehler wurden von @cfrick kommentiert.
'enthält?' Überprüft, ob ein Schlüssel z. ein Set oder eine Karte. es kann auch auf Array/Vektoren verwendet werden, um zu überprüfen, ob ein _index_ vorhanden ist. Es wird nicht auf Seqs unterstützt. auch "Kopf" gibt es einen Wert von Ihrem 'a-seq' (der erste) - und' leer? 'ist für die Überprüfung, wenn eine Liste leer ist. – cfrick