Reputation: 441
I have a list of string like this called F:
("hello word i'am walid" "goodbye madame")
=> this list contain two elements of string
and I have another list call S like this ("word" "madame")
=> this contain two words
now I want to remove the elements of the list S from each string of the list F and the output should be like this ("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)))
example:
(remove-string "walid" "hello i'am walid")
=> the output "hello i'am"
but there is a problem
example:
(remove-string "wa" "hello i'am walid")
=> the output "hello i'am lid"
but the output should be like this "hello i'am walid"
in another word i wont the remove the exact word from the string
please help me and thank's
Upvotes: 0
Views: 616
Reputation: 51561
You can use the cl-ppcre
library for regular expressions. Its regex flavour understands the word boundary \b
.
The replacement could work like this:
(cl-ppcre:regex-replace-all "\\bwa\\b" "ba wa walid" "")
=> "ba walid"
I guess that you want to collapse any whitespace around the removed word into one:
(cl-ppcre:regex-replace-all "\\s*\\bwa\\b\\s*" "ba wa walid" " ")
=> "ba walid"
See the documentation linked above.
UPDATE: You extended the question to punctuation. That's actually a tad more complicated, since you now have three kinds of characters: alphanumeric, punctuation, and whitespace.
I can't give a complete solution here, but the outline I envision is to create boundary definitions between all three of these kinds. You need positive/negative lookaheads/lookbehinds for that. Then you look at the replaced string, whether it starts or ends with punctuation and append or prepend the corresponding boundary to the effective expression.
For defining the boundaries in a readable manner, the parse tree syntax of cl-ppcre might prove useful.
Upvotes: 3
Reputation: 2671
The Common Lisp Cookbook provides this function:
(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)))
Using that function:
(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))
Upvotes: 1