lisp从另一个列表中删除一个列表的内容

时间:2015-05-17 23:33:21

标签: lisp common-lisp

我有一个名为F的字符串列表:

("hello word i'am walid" "goodbye madame") =>此列表包含两个字符串

元素

我有另一个列表调用S这样("word" "madame") =>这包含两个单词

现在我想从列表F的每个字符串中删除列表S的元素,输出应该像这样("hello i'am walid" "goodbye")

我发现了这个功能:

(defun remove-string (rem-string full-string &key from-end (test #'eql)
                      test-not (start1 0) end1 (start2 0) end2 key)
  "returns full-string with rem-string removed"
  (let ((subst-point (search rem-string full-string 
                             :from-end from-end
                             :test test :test-not test-not
                             :start1 start1 :end1 end1
                             :start2 start2 :end2 end2 :key key)))
    (if subst-point
        (concatenate 'string
                     (subseq full-string 0 subst-point)
                     (subseq full-string (+ subst-point (length rem-string))))
        full-string)))

例如: (remove-string "walid" "hello i'am walid") =>输出"hello i'am"

但是有问题

例如: (remove-string "wa" "hello i'am walid") =>输出"hello i'am lid"

但是输出应该像这个"hello i'am walid"在另一个词中我不会从字符串中删除确切的单词

请帮帮我,谢谢

2 个答案:

答案 0 :(得分:3)

您可以将cl-ppcre库用于正则表达式。它的正则表达式风格理解单词边界\b

替换可以这样工作:

(cl-ppcre:regex-replace-all "\\bwa\\b" "ba wa walid" "")

=> "ba  walid"

我想你想要将删除的单词周围的任何空格折叠成一个:

(cl-ppcre:regex-replace-all "\\s*\\bwa\\b\\s*" "ba wa walid" " ")

=> "ba walid"

请参阅上面链接的文档。

更新:您将问题扩展为标点符号。这实际上有点复杂,因为你现在有三种字符:字母数字,标点符号和空格。

我不能在这里提供完整的解决方案,但我设想的大纲是在所有这三种类型之间创建边界定义。你需要正面/负面的前瞻/外观。然后你看看被替换的字符串,无论是以标点符号开头还是结尾,并将相应的边界附加或附加到有效表达式。

为了以可读的方式定义边界,cl-ppcre的解析树语法可能证明是有用的。

答案 1 :(得分:1)

Common Lisp Cookbook提供此功能:

(defun replace-all (string part replacement &key (test #'char=))
"Returns a new string in which all the occurences of the part 
is replaced with replacement."
    (with-output-to-string (out)
      (loop with part-length = (length part)
            for old-pos = 0 then (+ pos part-length)
            for pos = (search part string
                              :start2 old-pos
                              :test test)
            do (write-string string out
                             :start old-pos
                             :end (or pos (length string)))
            when pos do (write-string replacement out)
            while pos))) 

使用该功能:

(loop for raw-string in '("hello word i'am walid" "goodbye madame")
        collect (reduce (lambda (source-string bad-word)
                          (replace-all source-string bad-word ""))
                        '("word" "madame")
                     :initial-value raw-string))