What's the idiomatic way in Clojure to implement take-while-and-n-more
below:
=> (take-while-and-n-more #(<= % 3) 1 (range 10))
(0 1 2 3 4)
My try is:
(defn take-while-and-n-more [pred n coll]
(let
[take-while-result (take-while pred coll)
n0 (count take-while-result)]
(concat
take-while-result
(into [] (take n (drop n0 coll))))))
I would use split-with, which is equivalent of getting results of both take-while and drop-while for the same parameters:
(defn take-while-and-n-more [pred n coll]
(let [[head tail] (split-with pred coll)]
(concat head (take n tail))))
Yet another way:
(defn take-while-and-n-more [pred n coll]
(let [[a b] (split-with pred coll)]
(concat a (take n b))))
The following code is a modified version of Clojures take-while
. Where Clojures take-while
returns nil
as a default case (when the predicate does not match), this one invokes take
to take the the additional items after the predicate fails.
Note that unlike versions using split-with
, this version traverses the sequence only once.
(defn take-while-and-n-more
[pred n coll]
(lazy-seq
(when-let [s (seq coll)]
(if (pred (first s))
(cons (first s) (take-while-and-n-more pred n (rest s)))
(take n s)))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With