如何在不使用任何内置函数的情况下将主输入字符串中的子字符串替换为另一个子字符串?

时间:2014-03-11 18:36:55

标签: clojurescript

我使用任何一个内置函数(如find(),replace()等)在网络中搜索的每个函数。我在学术书籍,图书馆和互联网上做过研究,但我找不到解决方案。请问您是否可以提供实现上述功能的算法,而无需使用任何内置函数?

1 个答案:

答案 0 :(得分:2)

好吧,让我们先尝试解决一些更简单的问题,然后逐步解决字符串替换问题。首先,我们如何确定两个字符串是否相等?相当直截了当吧?如果字符串具有相同的长度,并且具有相同顺序的相同字符,那么它们是相等的:

(defn str-eq? [s1 s2]
  (and (= (count s1) (count s2))
       (every? identity
               (map = s1 s2))))

好的,让我们尝试检查字符串是否有其他字符串作为前缀。事实证明这有一个几乎相同的解决方案,我们只是简化了两个字符串长度相同的要求:

(defn str-prefix? [s prefix]
  (and (>= (count s) (count prefix))
       (every? identity
               (map = s prefix))))

现在,让我们开始考虑如何在某些字符串中找到所有出现的字符串s1。好吧,如果我们采用s的所有后缀,从最长到最短排序,我们可以通过检查哪个后缀s1是前缀来确定s1在s1中出现的位置:

(defn str-suffixes [s]
  (->> s
       (iterate next)
       (take (inc (count s))) ;; make sure we include the empty string
       (map #(apply clojure.core/str %))))

(defn str-find [s s1]
  (->> (str-suffixes s)
       (map (fn [index suffix] 
              (if (str-prefix? suffix s1) 
                index 
                nil))
            (iterate inc 0))
       (filter identity)))

最后,是替换字符串的时间。我们将从简单的情况开始,其中字符串s1在索引处出现在字符串s中最多一次。只需将索引前的所有内容与替换字符串s2以及s中s1出现后的所有内容连接起来:

(defn str-replace [s s1 s2]
  (reduce (fn [s index]
            (apply clojure.core/str 
                   (concat (take index s)
                           s2
                           (drop (+ index (count s1)) s))))
          s
          (str-find s s1)))

如果s1多次出现,您会发现这不起作用。这是因为str-find以递增的顺序给出了结果。我们每次更换字符串时,都会在字符串后面使索引无效。要解决这个问题,我们只需处理从最大到最小的每个索引:

(defn str-replace [s s1 s2]
  (reduce (fn [s index]
            (apply clojure.core/str 
                   (concat (take index s)
                           s2
                           (drop (+ index (count s1)) s))))
          s
          (sort > (str-find s s1))))

这就是行动:

(str-replace "foobar" "foo" "baz")
=> "bazbar"
(str-replace "foobar" "bar" "baz")
=> "foobaz"
(str-replace "foobarbarfoo" "bar" "bazz")
=> "foobazzbazzfoo"
(str-replace "foobar" "z" "baz")
=> "foobar"

当解决这样的问题时,有助于考虑其他类似的操作,以及它们如何与您尝试实施的操作相关联。如果您有任何问题,请告诉我。