Subsequence replacement function

Is there a function that could replace subsequences? For example:

user> (good-fnc [1 2 3 4 5] [1 2] [3 4 5])
;; => [3 4 5 3 4 5]

      

I know there are for strings clojure.string/replace

:

user> (clojure.string/replace "fat cat caught a rat" "a" "AA")
;; => "fAAt cAAt cAAught AA rAAt"

      

Is there something similar for vectors and lists?

+3


source to share


3 answers


Here's a version that plays well with lazy inputs. Note that it can accept an infinite lazy sequence (range)

without an infinite loop, as the loop based version will.

(defn sq-replace
  [match replacement sq]
  (let [matching (count match)]
    ((fn replace-in-sequence [[elt & elts :as sq]]
       (lazy-seq
        (cond (empty? sq)
              ()
              (= match (take matching sq))
              (concat replacement (replace-in-sequence (drop matching sq)))
              :default
              (cons elt (replace-in-sequence elts)))))
     sq)))

#'user/sq-replace
user> (take 10 (sq-replace [3 4 5] ["hello, world"] (range)))
(0 1 2 "hello, world" 6 7 8 9 10 11)

      



I allowed the sequence argument to be the last argument, as this is the Clojure convention for functions that execute sequence.

+1


source


Does this work for you?



(defn good-fnc [s sub r]
  (loop [acc []
         s s]
    (cond
      (empty? s) (seq acc)
      (= (take (count sub) s) sub) (recur (apply conj acc r)
                                          (drop (count sub) s))
      :else (recur (conj acc (first s)) (rest s)))))

      

+2


source


My previous (now deleted) answer was wrong because it wasn't as trivial as I thought at first, here's my second attempt:

(defn seq-replace
  [coll sub rep]
  (letfn [(seq-replace' [coll]
            (when-let [s (seq coll)]
              (let [start (take (count sub) s)
                    end (drop (count sub) s)]
                (if (= start sub)
                  (lazy-cat rep (seq-replace' end))
                  (cons (first s) (lazy-seq (seq-replace' (rest s))))))))]
    (seq-replace' coll)))

      

+1


source







All Articles