clojure:从句子中删除一组字符串

时间:2014-11-16 11:23:40

标签: string replace clojure

我有句“中国北京上海美国澳大利亚”和一组单词#{“USA”“australia”}

现在我正在编写一个函数,它将输入作为句子和一组单词,并从句子中删除:

(defn remove-words-from-sentence [sentence words]
  (for [w words] (-> sentence
                     (.replaceAll w "")))

注意:我希望替换确切的单词出现..所以如果单词包含字母“a”,那么所有的a都不应该被替换为句子,只有单词a应该被替换。

但是上面的功能不起作用,有什么帮助?

4 个答案:

答案 0 :(得分:0)

for迭代给定的seq,产生另一个序列。因此,您要生成一个列表,其中的元素分别代表每个替换,但不会合并。

你想要的是先替换第一个单词,然后 - 在替换的结果上 - 删除第二个单词,依此类推。这是reduce的典型案例:

(defn remove-words-from-sentence
  [sentence words]
  (reduce #(.replace % %2 "") sentence words))

(请注意,replacereplaceAll的作用相同,但使用文字替换,不允许使用正则表达式。)

编辑:这只是修复了OP尝试做的事情。它可能会产生不需要的结果,例如其中一个词是" eij" (因为它将删除那部分"北京")。解决这个问题的一种方法是使用(.replaceAll % (str "\\b\\Q" %2 "\\E\\b\\s*") "")进行替换;然后trim结果。因此,更可靠的版本可能如下所示:

(require '[clojure.string :as string])
(defn remove-words-from-sentence
  [sentence words]
  (let [pattern (->> (for [w words] (str "\\b\\Q" w "\\E\\b"))
                     (string/join "|")
                     (format "(%s)\\s*"))]
    (.trim (.replaceAll sentence pattern ""))))

但这一切都取决于OP想要的东西。

答案 1 :(得分:0)

你能做到的一种方法是将句子分成单个单词,并在一个集合中删除单词,并过滤出句子中的单词。

(let [sentence (clojure.string/split (read-line) #" ")
      words (set (clojure.string/split (read-line) #" "))]
  (clojure.string/join " "
                       (filter (complement words)
                               sentence)))



user=> china beijing shanghai USA australia ;;input sentence
user=> china USA ;;input words
user=> "beijing shanghai australia" ;;output

编辑:

Thumbnail提请我注意(filter (complement pred) coll)相当于(remove pred coll)。您可以通过查看remove

的源代码来验证这一点
(source remove)
(defn remove
  "Returns a lazy sequence of the items in coll for which
  (pred item) returns false. pred must be free of side-effects."
  {:added "1.0"
   :static true}
  [pred coll]
  (filter (complement pred) coll))
nil

所以可以使用remove代替

(let [sentence (clojure.string/split (read-line) #" ")
      words (set (clojure.string/split (read-line) #" "))]
  (clojure.string/join " " (remove words sentence)))

这种方式更具可读性。您可以将其读作"从句子中删除单词"。

答案 2 :(得分:0)

user> (defn remove-words-from-sentence
        [sentence & words]
        (loop [sentence sentence
               ws words]
          (if-not (seq ws)
            sentence
            (recur
             (clojure.string/replace sentence (first ws) "")
             (rest ws)))))
#'user/remove-words-from-sentence
user> (remove-words-from-sentence "Hello, World" "World")
;=> "Hello, "
user> (remove-words-from-sentence "Hello, World" "ll" "o" "H")
;=> "e, Wrld"

答案 3 :(得分:0)

到目前为止,答案并未处理指定输入类型(字符串和集合)的问题

由于输入的单词在问题中被指定为一个集合,而句子是一个字符串 - 最简单的解决方案可能是使用集合 - 也很容易理解;

(defn remove-words-from-sentence [sentence words]
    (str/join " "(set/difference (into #{} (str/split sentence #" ")) words))
)

按宣传方式工作:

(remove-words-from-sentence "china beijing shanghai USA australia" #{"USA" "australia"}) 
"beijing china shanghai"