Idomatically insert elements between two elements in a sequence that executes a predicate?

Say I have a predicate that takes two elements and returns true for false. I want to insert an element between each consecutive pair in a sequence that returns true for the predicate. I came up with a couple of solutions, but I was wondering what would be the idiomatic way to do this functionally in Clojure?

+5
source share
3 answers

This is my attempt:

(defn interpose-predicated [pred in coll]
  (if (next coll)
    (->> coll
         (partition 2 1)
         (mapcat (comp next #(if (apply pred %) (interpose in %) %)))
         (cons (first coll)))
    coll))
+3
source

My first project will look like

(defn insert-between [pred inter coll]
  (lazy-seq
   (when-let [s (seq coll)]
     (cons (first s)
           (mapcat (fn [[left right]]
                     (if (pred left right)
                       [inter right]
                       [right]))
                   (partition 2 1 s))))))


user> (insert-between < :less [1 6 7 4 3])
(1 :less 6 :less 7 4 3)

, , - , , . .

+4

This is a normal SO [clojure] race to come up with the most concise solution. :-) I usually do not win, but I participate a lot in this process. Anyway, here is my solution:

(defn interpose-p [[a b & _ :as s] d p]
  (when-not (empty? s)
    (if (and (not (nil? b)) (p a b))
      (cons a (cons d (interpose-p (rest s) d p)))
      (cons a (interpose-p (rest s) d p)))))

(interpose-p [1 2 3 2 1 2 3] "," <) 

(1 "," 2 "," 3 2 1 "," 2 "," 3)

Update . Although the discussion is completed, an updated solution is presented here, taking into account all the comments. This time should be enough industrial power if my understanding of lazy seq is correct. It is templated from lazy-seq discussion here .

(defn interpose-p
  [pred coll sep]
  (let [f (fn [c]
            (when-let [[a b & _ :as s] (seq c)]
              (if (and b (pred a b))
                (list* a sep (interpose-p pred (rest s) sep))
                (list* a (interpose-p pred (rest s) sep)))))]
    (lazy-seq (f coll))))
+3
source

All Articles