Function which verifies if a string is includes in an other one in Lisp -
i trying write function verifies if string included in 1 in lisp cannot
for example :
(string-include 'abd 'abbbe) => nil (string-include 'ghf 'dghfd) => ghf here function:
(defun string-include (string1 string2) (cond ((not string1) 0) ((not string2) 0) ((.... (string1) (string2)) (string1 (string-include string1 (cdr string2)))) ((string-include string1 (cdr string2)) ) )
return index or substring, not symbol
in question, used example:
(string-include 'abd 'abbbe) => nil (string-include 'ghf 'dghfd) => ghf
assuming you're returning symbols nil , ghf, you'll run ambiguity if ever want check whether string contains substring nil. e.g., approach, you'll have:
(string-include 'nil 'vanilla) => nil did return nil because "nil" in "vanilla", because isn't? it's ambiguous , can't tell. instead, return actual string, since string "nil" true value. better, if return index of string, find out where in other string first string appears. that's way built in function search behaves, instance.
directly, using search
you can implement in terms of search:
(defun substringp (needle haystack &key (test 'char=)) "returns index of first occurrence of string designated needle within string designated haystack, or nil if not occur. characters within string compared test, defaults char= (for case-sensitive comparison)." (search (string needle) (string haystack) :test test)) note use of string function convert string designators (characters, strings, , symbols) strings designate. remember standard settings, reader upcases names of symbols, symbol cat designates string "cat". finally, since returns result search, double duty you: returns index of first occurrence if there occurrence, , nil otherwise. remember except nil true value (even 0), can use result boolean or index (as long check it's not nil). here examples:
cl-user> (substringp "cat" "concatenate") 3 cl-user> (substringp "dog" "concatenate") nil ;; default upcasing of symbol names means ;; result of 'cat symbol named "cat", not ;; in "concatenate". cl-user> (substringp 'cat "concatenate") nil ;; can test characters char-equal, ;; case insensitive, in case "cat" in ;; "concatenate". cl-user> (substringp 'cat "concatenate" :test 'char-equal) 3 using recursion
your code, , code uselpa showed in answer, more recursive in nature. in , of not problem, recursive string processing in common lisp prone few pitfalls. it's inefficient make lots of new stings using subseq, lots of sequence functions in common lisp take :start , :end arguments, or in case of functions take 2 sequences, :start1, :end1, :start2, , :end2 arguments. using these, can recurse , change indices strings, rather creating entirely new strings. instance, string= lets compare 2 strings.
;; "toc" in both "octocat" , "toccata" cl-user> (string= "octocat" "toccata" :start1 2 :end1 5 :end2 3) t working these kinds of functions requires bit of care make sure don't provide indices out of range, it's not bad, , don't end copying strings. here's version of substringp accepts these start , end parameters, , uses local recursive function actual processing.
(defun substringp (string1 string2 &key (start1 0) (end1 nil) (start2 0) (end2 nil)) "returns index of first occurence of substring of string1 bounded start1 , end1 within substring of string2 bounded start2 , end2, or nil if string not appear. index position within string2 whole." ;; first, compute actual strings designated string1 , ;; string2, , values end1 , end2, default ;; length of respective strings. length of ;; substring in string1 we're looking for. done ;; once. actual recursive portion handled local ;; function %substringp. (let* ((string1 (string string1)) (string2 (string string2)) (end1 (or end1 (length string1))) (end2 (or end2 (length string2))) (len1 (- end1 start1))) (labels ((%substringp (start2 &aux (end2-curr (+ start2 len1))) (cond ;; if end2-curr past end2, we're done, , ;; string not found. ((not (< end2-curr end2)) nil) ;; otherwise, check whether substrings match. if ;; do, return current start2, ;; index of substring within string2. ((string= string1 string2 :start1 start1 :end1 end1 :start2 start2 :end2 end2-curr) start2) ;; if doesn't match, recurse, starting 1 ;; character farther string2. (t (%substringp (1+ start2)))))) (%substringp start2))))
Comments
Post a Comment