Hi there,
I can't seem to find functions for searching a string in Common Lisp.
I'd like to do such a simple thing as finding out if a string has a
substring in it, but can't seem to find a function to do that. Am I
blind or what?
Yes, of course it's easy to write one myself, its just that I can't
belive there's not such function CL...
--
"Now the storm has passed over me
I'm left to drift on a dead calm sea
And watch her forever through the cracks in the beams
Nailed across the doorways of the bedrooms of my dreams"
From: Marco Baringer
Subject: Re: string searching functions in CL
Date:
Message-ID: <m2lktvm8df.fsf@bese.it>
Nikola Skoric <·········@net4u.hr> writes:
> Hi there,
>
> I can't seem to find functions for searching a string in Common Lisp.
> I'd like to do such a simple thing as finding out if a string has a
> substring in it, but can't seem to find a function to do that. Am I
> blind or what?
search - http://www.lisp.org/HyperSpec/Body/fun_search.html
see also cl-ppcre (http://www.weitz.de/cl-ppcre/)
--
-Marco
Ring the bells that still can ring.
Forget the perfect offering.
There is a crack in everything.
That's how the light gets in.
-Leonard Cohen
In article <··············@bese.it>, ··@bese.it says...
> Nikola Skoric <·········@net4u.hr> writes:
>
> > Hi there,
> >
> > I can't seem to find functions for searching a string in Common Lisp.
> > I'd like to do such a simple thing as finding out if a string has a
> > substring in it, but can't seem to find a function to do that. Am I
> > blind or what?
>
> search - http://www.lisp.org/HyperSpec/Body/fun_search.html
>
> see also cl-ppcre (http://www.weitz.de/cl-ppcre/)
OK, OK, I hate being a n00b. I forgot that strings are sequences and
that functions for sequences work on strings.
And, now one for which I won't be surprised if ti didn't exist: a
function to explode a string in a PHP's manner. That is, (explode " "
"foo bar") returns ("foo" "bar"). Does something like that exist? I
promise this is my last dumb question for next 2 months ;-)
--
"Now the storm has passed over me
I'm left to drift on a dead calm sea
And watch her forever through the cracks in the beams
Nailed across the doorways of the bedrooms of my dreams"
Nikola Skoric <·········@net4u.hr> writes:
> In article <··············@bese.it>, ··@bese.it says...
>> Nikola Skoric <·········@net4u.hr> writes:
>>
>> > Hi there,
>> >
>> > I can't seem to find functions for searching a string in Common Lisp.
>> > I'd like to do such a simple thing as finding out if a string has a
>> > substring in it, but can't seem to find a function to do that. Am I
>> > blind or what?
>>
>> search - http://www.lisp.org/HyperSpec/Body/fun_search.html
>>
>> see also cl-ppcre (http://www.weitz.de/cl-ppcre/)
>
> OK, OK, I hate being a n00b. I forgot that strings are sequences and
> that functions for sequences work on strings.
>
> And, now one for which I won't be surprised if ti didn't exist: a
> function to explode a string in a PHP's manner. That is, (explode " "
> "foo bar") returns ("foo" "bar"). Does something like that exist? I
> promise this is my last dumb question for next 2 months ;-)
Nope. But the SPLIT-SEQUENCE library does what you want:
<http://www.cliki.net/SPLIT-SEQUENCE>
-Peter
--
Peter Seibel * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp * http://www.gigamonkeys.com/book/
From: Marco Baringer
Subject: Re: string searching functions in CL
Date:
Message-ID: <m2hd4jm80x.fsf@bese.it>
Nikola Skoric <·········@net4u.hr> writes:
> In article <··············@bese.it>, ··@bese.it says...
>> Nikola Skoric <·········@net4u.hr> writes:
>>
>> > Hi there,
>> >
>> > I can't seem to find functions for searching a string in Common Lisp.
>> > I'd like to do such a simple thing as finding out if a string has a
>> > substring in it, but can't seem to find a function to do that. Am I
>> > blind or what?
>>
>> search - http://www.lisp.org/HyperSpec/Body/fun_search.html
>>
>> see also cl-ppcre (http://www.weitz.de/cl-ppcre/)
>
> OK, OK, I hate being a n00b. I forgot that strings are sequences and
> that functions for sequences work on strings.
>
> And, now one for which I won't be surprised if ti didn't exist: a
> function to explode a string in a PHP's manner. That is, (explode " "
> "foo bar") returns ("foo" "bar"). Does something like that exist? I
> promise this is my last dumb question for next 2 months ;-)
that does not in fact exist. what you have is this:
http://www.cliki.net/SPLIT-SEQUENCE
it's a very small lib, has been stable for a long time and is used by
a bunch of other libs.
--
-Marco
Ring the bells that still can ring.
Forget the perfect offering.
There is a crack in everything.
That's how the light gets in.
-Leonard Cohen
> http://www.cliki.net/SPLIT-SEQUENCE
>
> it's a very small lib, has been stable for a long time and is used by
> a bunch of other libs.
Nice, but VERY slow when input is a list.
Naive wersion (works only on lists):
(defun split-list-if (list test &aux (start list) (end list))
(loop while (and end (setq start (member-if-not test end)))
collect (ldiff start (setq end (member-if test start)))))
;;; Speed test:
CL-USER> (defparameter *test-data*
(with-open-file (stream
#P"/home/tichy/emacs/man/man1/emacs.1"
:direction :input)
(loop with char while (setq char (read-char stream nil
nil))
collect char)))
CL-USER> (length *test-data*)
15837
CL-USER> (defvar *test-result*)
CL-USER> (defun test-split-list-if ()
(setq *test-result*
(split-list-if *test-data*
(lambda (x)
(member x '(#\Space #\Newline
#\Tab)))))
(values))
CL-USER> (defun test-split-sequence-if ()
(setq *test-result*
(cl-utilities:split-sequence-if
(lambda (x) (member x '(#\Space #\Newline #\Tab)))
*test-data*
:remove-empty-subseqs t))
(values))
CL-USER> (time (test-split-list-if))
Evaluation took:
0.001 seconds of real time
0.001 seconds of user run time ; !!!
0.0 seconds of system run time
0 page faults and
147,456 bytes consed.
; No value
CL-USER> (time (test-split-sequence-if))
Evaluation took:
0.746 seconds of real time
0.744 seconds of user run time ; !!!
0.0 seconds of system run time
0 page faults and
131,072 bytes consed.
; No value
Regards, Szymon.
Nikola Skoric schrieb:
> In article <··············@bese.it>, ··@bese.it says...
> > Nikola Skoric <·········@net4u.hr> writes:
> >
> > > Hi there,
> > >
> > > I can't seem to find functions for searching a string in Common Lisp.
> > > I'd like to do such a simple thing as finding out if a string has a
> > > substring in it, but can't seem to find a function to do that. Am I
> > > blind or what?
> >
> > search - http://www.lisp.org/HyperSpec/Body/fun_search.html
> >
> > see also cl-ppcre (http://www.weitz.de/cl-ppcre/)
>
> OK, OK, I hate being a n00b. I forgot that strings are sequences and
> that functions for sequences work on strings.
>
> And, now one for which I won't be surprised if ti didn't exist: a
> function to explode a string in a PHP's manner. That is, (explode " "
> "foo bar") returns ("foo" "bar"). Does something like that exist? I
> promise this is my last dumb question for next 2 months ;-)
>
> --
> "Now the storm has passed over me
> I'm left to drift on a dead calm sea
> And watch her forever through the cracks in the beams
> Nailed across the doorways of the bedrooms of my dreams"
try this:
(defun tokens (str test start)
"Find tokens in STR separated by TEST from position START."
(let ((p1 (position-if test str :start start)))
(if p1
(let ((p2 (position-if #'(lambda (c)
(not (funcall test c)))
str :start p1)))
(cons (subseq str p1 p2)
(if p2
(tokens str test p2)
nil)))
nil)))
(defun constituent (c)
"the separating function"
(and (graphic-char-p c)
(not (char= c #\ ))))
(defun find-character (char string)
"See if the character appears in the string."
(declare (character char) (simple-string string))
(loop for ch across string
when (eql ch char) return ch))
[26]> (tokens "a clock is running" #'constituent 0)
("a" "clock" "is" "running")
keyboard
keyboard wrote:
> Nikola Skoric schrieb:
>
> > In article <··············@bese.it>, ··@bese.it says...
> > > Nikola Skoric <·········@net4u.hr> writes:
> > >
> > > > Hi there,
> > > >
> > > > I can't seem to find functions for searching a string in Common Lisp.
> > > > I'd like to do such a simple thing as finding out if a string has a
> > > > substring in it, but can't seem to find a function to do that. Am I
> > > > blind or what?
> > >
> > > search - http://www.lisp.org/HyperSpec/Body/fun_search.html
> > >
> > > see also cl-ppcre (http://www.weitz.de/cl-ppcre/)
> >
> > OK, OK, I hate being a n00b. I forgot that strings are sequences and
> > that functions for sequences work on strings.
> >
> > And, now one for which I won't be surprised if ti didn't exist: a
> > function to explode a string in a PHP's manner. That is, (explode " "
> > "foo bar") returns ("foo" "bar"). Does something like that exist? I
> > promise this is my last dumb question for next 2 months ;-)
> >
> > --
> > "Now the storm has passed over me
> > I'm left to drift on a dead calm sea
> > And watch her forever through the cracks in the beams
> > Nailed across the doorways of the bedrooms of my dreams"
>
> try this:
>
> (defun tokens (str test start)
> "Find tokens in STR separated by TEST from position START."
> (let ((p1 (position-if test str :start start)))
> (if p1
> (let ((p2 (position-if #'(lambda (c)
> (not (funcall test c)))
> str :start p1)))
> (cons (subseq str p1 p2)
> (if p2
> (tokens str test p2)
> nil)))
> nil)))
>
> (defun constituent (c)
> "the separating function"
> (and (graphic-char-p c)
> (not (char= c #\ ))))
>
> (defun find-character (char string)
> "See if the character appears in the string."
> (declare (character char) (simple-string string))
> (loop for ch across string
> when (eql ch char) return ch))
>
> [26]> (tokens "a clock is running" #'constituent 0)
> ("a" "clock" "is" "running")
>
> keyboard
Version with LOOP is shorter:
(defun tokens (str test &optional (start 0) &aux (end 0))
(loop while (and end (setq start (position-if test str :start end)))
collect (subseq str start (setq end (position-if-not test str
:start start)))))
CL-USER> (tokens "a clock is running" #'constituent)
("a" "clock" "is" "running")
Btw, there is function CHAR/= (equivalent of (NOT (CHAR= ...))).
Another variation:
(defun split-string-on-char (string char)
(loop with (start end) = '(0 0)
while (and end (setq start (position-if (lambda (c) (char/=
char c)) string :start end)))
collect (subseq string start (setq end (position char string
:start start)))))
CL-USER> (split-string-on-char "a clock is running" #\Space)
("a" "clock" "is" "running")
Regards, Szymon.
Marco Baringer <··@bese.it> wrote:
+---------------
| Nikola Skoric <·········@net4u.hr> writes:
| > I'd like to do such a simple thing as finding out if a string has a
| > substring in it, but can't seem to find a function to do that.
|
| search - http://www.lisp.org/HyperSpec/Body/fun_search.html
| see also cl-ppcre (http://www.weitz.de/cl-ppcre/)
+---------------
Don't forget MISMATCH <http://www.lisp.org/HyperSpec/Body/fun_mismatch.html>
I actually tend to find myself using it rather more than SEARCH
for simple pattern matches, deconstructions, and peeling off
prefixes & suffixes. Further, alternating calls of MISMATCH and
SEARCH are often useful, using the results of each call in the
:START or [with :FROM-END T] :END keyword args in the next call.
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607