2014-09-05 32 views
3

是否有可以替换子序列的函数?例如:替换子序列的函数

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

我知道有clojure.string/replace字符串:

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

是否有向量和列表类似的东西?

回答

1

这是一个可以和懒惰seq输入很好地玩的版本。请注意,它可以采用无限延迟序列(range),而无需循环无限循环版本。

(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) 

我把制作序列参数的最后一个参数的自由,因为这是Clojure中的约定对于行走序列的功能。

+0

它已被修复,谢谢。 – noisesmith 2014-09-07 05:22:23

+1

我用'(应用str(sq-replace“a”“AA”“胖猫抓到一只老鼠”))测试了我的解决方案(后来证明这是一个伪装)老鼠“!有什么不对?提示:'(应用str(sq-replace(seq”a“)”AA“”肥猫抓老鼠“)''产生''fAAt cAAt cAAught AA rAAt”'。 ?)类型检查程序可以帮助的情况。 – Thumbnail 2014-09-07 09:20:03

2

这是否适合您?

(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))))) 
+0

是它,但我感兴趣的标准功能(我认为这是相当基本的操作,所以如果有字符串的东西,应该有一些向量和列表...) – Mark 2014-09-05 17:07:47

+0

Clojure字符串操作大多只是jvm互操作。一般序列不支持字符串的许多操作。 – noisesmith 2014-09-05 17:29:09

+0

@noisesmith,所以这意味着没有标准的功能呢? – Mark 2014-09-05 18:00:04

1

我以前的(现已删除)的答案是不正确的,因为这不是因为我首先想到的是琐碎的,这里是我的第二次尝试:

(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)))