Let’s first write a function to check the outputs. Since it’s quite simple, I’ll
use the example from the problem definition and a couple of corner cases:
(defn spy [x] (prn x) x)
(defn seqs-match? [a b]
;; we don't care about size because the input might be an infinite seq
(every? (partial apply =) (zipmap a b)))
(defn check-fn [f]
(doseq [{:keys [testcase expected]} [{:testcase [3 [:a :b :c :d :e :f :g]], :expected [:a :b :d :e :g]}
{:testcase [3 [:a :b :c :d :e :f :g :h :i]], :expected [:a :b :d :e :g :h]}
{:testcase [3 [:a :b]], :expected [:a :b]}
{:testcase [3 (range)], :expected [0 1 3 4 6 7 9 10 12]}
{:testcase [3 []], :expected []}]
:let [actual (apply f testcase)]]
(if (seqs-match? actual expected)
(println "Match!")
(do (println "Mismatch :(")
(println (str " Expected: " (pr-str expected)))
(println (str " Actual : " (pr-str actual)))))))
The simplest way I could think of was indexing the collection and filtering it:
(defn drop-every-simple [n coll]
(->> coll
(map-indexed (fn [index v] [(mod (inc index) n) v]))
(filter (complement #(-> % first zero?)))
(map second)))
(check-fn drop-every-simple)
We can also write an arity to return an xform for it:
(defn drop-every
([n]
(comp
(map-indexed (fn [index v] [(mod (inc index) n) v]))
(filter (complement #(-> % first zero?)))
(map second)))
([n coll]
(sequence (drop-every n) coll)))
(check-fn drop-every)