Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Like needed

1 view
Skip to first unread message

Slobodan Blazeski

unread,
Sep 18, 2009, 7:25:42 PM9/18/09
to
Does anybody has string matching function that supports * joker
handy.

Intended use is something like:
(like "*widget" "textareaWidget") => "textareaWidget"
(like "*widget" "textareaControl") => nil

(like "common*" "common-lisp") =>"common-lisp"
(like "common*" "uncommon-web") =>"common-lisp"

(like "*bar* "foobarbaz") => "foobarbaz"
(like "*bar* "fizzbaz") => nil

Bobi
http://www.linkedin.com/in/slobodanblazeski

Pascal J. Bourguignon

unread,
Sep 18, 2009, 8:53:07 PM9/18/09
to
Slobodan Blazeski <slobodan...@gmail.com> writes:

> Does anybody has string matching function that supports * joker
> handy.
>
> Intended use is something like:
> (like "*widget" "textareaWidget") => "textareaWidget"
> (like "*widget" "textareaControl") => nil
>
> (like "common*" "common-lisp") =>"common-lisp"
> (like "common*" "uncommon-web") =>"common-lisp"
>
> (like "*bar* "foobarbaz") => "foobarbaz"
> (like "*bar* "fizzbaz") => nil

Easy:

(defun like (pattern string)
(values (ppcre:scan-to-strings
(ppcre:regex-replace-all "\\*" pattern ".*")
string)))


--
__Pascal Bourguignon__

Thomas A. Russ

unread,
Sep 18, 2009, 8:49:48 PM9/18/09
to
Slobodan Blazeski <slobodan...@gmail.com> writes:

> Does anybody has string matching function that supports * joker
> handy.

Well, I did hack something up like that as an extention of one of the CL
regular expression packages.

I'll send it to you by private EMail.

I wonder how difficult it would be to add that as an alternate input
language to Lawrence E. Freil nregex.lisp package.

--
Thomas A. Russ, USC/Information Sciences Institute

Pascal J. Bourguignon

unread,
Sep 18, 2009, 9:33:11 PM9/18/09
to

Actually, you may want to first quote the pattern first, and you seem
to want case insensitivity:

(defun like (pattern string)
(values (ppcre:scan-to-strings

(ppcre:crate-scanner
(ppcre:regex-replace-all "\\\\\\*"
(ppcre:quote-meta-chars pattern)
".*")
:case-insensitive-mode t)
string)))


--
__Pascal Bourguignon__

Kenneth Tilton

unread,
Sep 19, 2009, 12:18:50 AM9/19/09
to
Slobodan Blazeski wrote:
> Does anybody has string matching function that supports * joker
> handy.
>
> Intended use is something like:
> (like "*widget" "textareaWidget") => "textareaWidget"
> (like "*widget" "textareaControl") => nil
>
> (like "common*" "common-lisp") =>"common-lisp"
> (like "common*" "uncommon-web") =>"common-lisp"

You need my crystal-ball.lisp, methinks.

kt (Pleased that he is still the only one in this NG who can read.)

ps. Looking forward to the CLOS-based implementation from Costanza. k

Slobodan Blazeski

unread,
Sep 19, 2009, 4:08:52 AM9/19/09
to
On Sep 19, 3:33 am, p...@informatimago.com (Pascal J. Bourguignon)
wrote:


Thanks for their solutions to Pascal and Thomas. For my specific
problem below will do without adding dependencies on regexes:

(defun extractWidgets (tree)
(labels ((like-widget (str)
(and (> (length str) 6)
(string-equal "widget" (subseq str (- (length str)
6))))))
(unique (keep (f like-widget (princ-to-string x)) (flatten
tree)))))

The code clutter is due to unavailability of like else it would be
something like:
(defun extractWidgets (tree)
(unique (keep (f like "*widget" (princ-to-string x)) (flatten
tree)))))

The problem is Slava challenge discussed in http://pozorvlak.livejournal.com/89208.html

cheers
Bobi
http://www.linkedin.com/in/slobodanblazeski

Pascal J. Bourguignon

unread,
Sep 19, 2009, 4:34:40 AM9/19/09
to
Kenneth Tilton <kent...@gmail.com> writes:

> Slobodan Blazeski wrote:
>> Does anybody has string matching function that supports * joker
>> handy.
>> Intended use is something like:
>> (like "*widget" "textareaWidget") => "textareaWidget"
>> (like "*widget" "textareaControl") => nil
>> (like "common*" "common-lisp") =>"common-lisp"
>> (like "common*" "uncommon-web") =>"common-lisp"
>
> You need my crystal-ball.lisp, methinks.
>
> kt (Pleased that he is still the only one in this NG who can read.)

We've all seen the typo.

--
__Pascal Bourguignon__

Kenneth Tilton

unread,
Sep 19, 2009, 5:22:58 AM9/19/09
to

Mirko

unread,
Sep 19, 2009, 9:55:25 AM9/19/09
to
On Sep 19, 4:08 am, Slobodan Blazeski <slobodan.blaze...@gmail.com>
wrote:

Not sure, but you might simplify your labels code by using masmatch.
As was pointed out to me recently, subseq will generate a new sequence
that is immediately discarded. Mismatch will avoid that.

Mirko

Stanislaw Halik

unread,
Sep 19, 2009, 10:11:26 AM9/19/09
to
Slobodan Blazeski <slobodan...@gmail.com> writes:

I once wrote this, which naively implements MS-DOS-style patterns:

(defun wildcard-match (string pattern)
(declare (optimize (speed 3) (safety 0) (debug 1))
(type string string pattern))
(block success
(labels ((mat (string-pos pattern-pos)
(declare (type fixnum string-pos pattern-pos))
(let* ((string-ok (array-in-bounds-p string string-pos))
(string-char (and string-ok (aref string string-pos)))
(pattern-ok (array-in-bounds-p pattern pattern-pos))
(pattern-char (and pattern-ok (aref pattern pattern-pos))))
(cond
((and (not string-ok) (not pattern-ok))
(return-from success t))
((not pattern-ok))
(t
(case pattern-char
(#\? (when string-ok
(mat (1+ string-pos) (1+ pattern-pos))))
(#\* (cond
((= (1- (length pattern)) pattern-pos)
(return-from success t))
(string-ok
(loop
for i from string-pos below (length string)
do (mat i (1+ pattern-pos))))
(t
(return-from success t))))
(otherwise (when (and string-ok
(char= pattern-char string-char))
(mat (1+ string-pos) (1+ pattern-pos))))))))))
(mat 0 0)
nil)))

If you don't need #\? matching one character, you can remove it from the
„CASE” body.

--
polscy Lispnicy, łączmy się -- #lisp-pl na freenode
Lisp stuff: <http://tehran.lain.pl>

Vassil Nikolov

unread,
Sep 19, 2009, 1:24:05 PM9/19/09
to

On Sat, 19 Sep 2009 01:08:52 -0700 (PDT), Slobodan Blazeski <slobodan...@gmail.com> said:
> ...

> (labels ((like-widget (str)
> (and (> (length str) 6)
> (string-equal "widget" (subseq str (- (length str) 6))))))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Do it without SUBSEQ, i.e.

(string-equal "widget" str :start2 (- (length str) 6))

but, as already pointed out in the thread,

(defun widgetp (n &aux (c= #'char-equal))
"Test if the string (or the name of the symbol) N ends with \"widget\"."
(zerop (or (mismatch "widget" (string n) :from-end t :test c=) 0)))

is better (avoids the noise related to the length of the suffix).

Assuming we have FLATTEN, the whole thing may become something like

(defun widgets (tree)
(flet ((widgetp (n &aux (c= #'char-equal))
(zerop (or (mismatch "widget" (string n) :from-end t :test c=) 0))))
(remove-duplicates (remove-if-not #'widgetp (flatten tree)))))

(one may want to "promote" C= to a keyword parameter to WIDGETS, and
possibly use a paremeter instead of the literal "widget" as well,
renaming the function).

---Vassil.


--
"Even when the muse is posting on Usenet, Alexander Sergeevich?"

Slobodan Blazeski

unread,
Sep 20, 2009, 6:35:35 AM9/20/09
to

Thanks for the tip mismatch is better then subseq but string-equal is
just what I need.

Bobi

Slobodan Blazeski

unread,
Sep 20, 2009, 6:50:22 AM9/20/09
to
On Sep 19, 7:24 pm, Vassil Nikolov <vniko...@pobox.com> wrote:
> On Sat, 19 Sep 2009 01:08:52 -0700 (PDT), Slobodan Blazeski <slobodan.blaze...@gmail.com> said:> ...

> >   (labels ((like-widget (str)
> >              (and (> (length str) 6)
> >               (string-equal "widget" (subseq str (- (length str) 6))))))
>
>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
>   Do it without SUBSEQ, i.e.
>
>     (string-equal "widget" str :start2 (- (length str) 6))
Yes string-equal is the right thing to do it.

>
>   but, as already pointed out in the thread,
>
>     (defun widgetp (n &aux (c= #'char-equal))
>       "Test if the string (or the name of the symbol) N ends with \"widget\"."
>       (zerop (or (mismatch "widget" (string n) :from-end t :test c=) 0)))
>
>   is better (avoids the noise related to the length of the suffix).
Aha, you are right thanks.

>
>   Assuming we have FLATTEN, the whole thing may become something like
>
>     (defun widgets (tree)
>       (flet ((widgetp (n &aux (c= #'char-equal))
>                (zerop (or (mismatch "widget" (string n) :from-end t :test c=) 0))))
>         (remove-duplicates (remove-if-not #'widgetp (flatten tree)))))
>
>   (one may want to "promote" C= to a keyword parameter to WIDGETS, and
>   possibly use a paremeter instead of the literal "widget" as well,
>   renaming the function).
The last line is the same with my solution. I confess being guilty of
setfing function value of unique and keep to remove-duplicates and
remove-if-not. Later will have to add other functionality to unique
and keep to avoid confusion but for now I like my shorter names
better. Its very hard to compete on speed golf with languages that
have far shorter names thus making lisp solution look verbose.

cheers
Bobi

Vassil Nikolov

unread,
Sep 20, 2009, 12:32:09 PM9/20/09
to

On Sun, 20 Sep 2009 03:50:22 -0700 (PDT), Slobodan Blazeski <slobodan...@gmail.com> said:
> ...
> setfing function value of unique and keep to remove-duplicates and
> remove-if-not.

REMOVE-IF-NOT is KEEP-IF; (KEEP ...) would be (REMOVE ... :TEST-NOT #'EQL),
or (REMOVE ... :TEST (COMPLEMENT #'EQL)) if someone insists.

Vassil Nikolov

unread,
Sep 20, 2009, 12:36:52 PM9/20/09
to

On Sun, 20 Sep 2009 03:50:22 -0700 (PDT), Slobodan Blazeski <slobodan...@gmail.com> said:
> ...
> Its very hard to compete on speed golf with languages that
> have far shorter names thus making lisp solution look verbose.

Pick another competition: show (say) a Perl solution to someone who
does not know Perl, and a Lisp solution to someone who does not know
Lisp, and see which will be more understandable to its respective
reader.

Dmitriy Ivanov

unread,
Sep 30, 2009, 4:50:46 AM9/30/09
to
Stanislaw Halik wrote on Sat, 19 Sep 2009 16:11:26 +0200 18:11:

SH> Slobodan Blazeski <slobodan...@gmail.com> writes:
SH>
SH> I once wrote this, which naively implements MS-DOS-style patterns:
SH> | ...snip...|
SH> If you don't need #\? matching one character, you can remove it
SH> from the "CASE" body.

If one does not need #\?, he should use pathname-match-p :-)
--
Sincerely,
Dmitriy Ivanov
lisp.ystok.ru


Slobodan Blazeski

unread,
Sep 30, 2009, 8:27:53 AM9/30/09
to
On Sep 30, 10:50 am, "Dmitriy Ivanov" <divanov_nosp@m_aha.ru> wrote:
> Stanislaw Halik wrote on Sat, 19 Sep 2009 16:11:26 +0200 18:11:
>
> SH> Slobodan Blazeski <slobodan.blaze...@gmail.com> writes:
> SH>
> SH> I once wrote this, which naively implements MS-DOS-style patterns:
> SH> | ...snip...|
> SH> If you don't need #\? matching one character, you can remove it
> SH> from the "CASE" body.
>
> If one does not need #\?, he should use pathname-match-p :-)

(pathname-match-p "loginWidget" "*Widget")
T
(pathname-match-p "loginControl" "*Widget")
NIL


Great I knew that there must be some function in the hyperspec that's
doing just what I want and I only need to know its name.

Bobi

Slobodan Blazeski

unread,
Sep 30, 2009, 8:30:34 AM9/30/09
to
On Sep 20, 6:36 pm, Vassil Nikolov <vniko...@pobox.com> wrote:

> On Sun, 20 Sep 2009 03:50:22 -0700 (PDT), Slobodan Blazeski <slobodan.blaze...@gmail.com> said:
>
> > ...
> > Its very hard to compete on speed golf with languages that
> > have far shorter names thus making lisp solution look verbose.
>
>   Pick another competition
No way, I love golf. And harsh constraints quite often lead to very
clever solutions and as in this case discovery of many useful
utilities already present in the standard that I overlooked.

Bobi

Vassil Nikolov

unread,
Sep 30, 2009, 10:26:47 PM9/30/09
to

On Wed, 30 Sep 2009 05:27:53 -0700 (PDT), Slobodan Blazeski <slobodan...@gmail.com> said:
> ...
> (pathname-match-p "loginWidget" "*Widget")
> T
> (pathname-match-p "loginControl" "*Widget")
> NIL

> Great I knew that there must be some function in the hyperspec that's
> doing just what I want and I only need to know its name.

Let the programmer beware, though. The matching rules are
unspecified (implementation-dependent) and then oriented towards
pathnames, not towards general string matching, e.g.

(pathname-match-p "./foo" "foo")
(pathname-match-p "/foo" "//foo")

may return true.

Slobodan Blazeski

unread,
Oct 1, 2009, 1:11:16 PM10/1/09
to
On Oct 1, 4:26 am, Vassil Nikolov <vniko...@pobox.com> wrote:

> On Wed, 30 Sep 2009 05:27:53 -0700 (PDT), Slobodan Blazeski <slobodan.blaze...@gmail.com> said:
>
> > ...
> > (pathname-match-p "loginWidget" "*Widget")
> > T
> >  (pathname-match-p "loginControl" "*Widget")
> > NIL
> > Great I knew that there must be some function in the hyperspec that's
> > doing just what I want and I only need to know its name.
>
>   Let the programmer beware, though.  The matching rules are
>   unspecified (implementation-dependent) and then oriented towards
>   pathnames, not towards general string matching, e.g.
>
>     (pathname-match-p "./foo" "foo")
>     (pathname-match-p "/foo" "//foo")
>
>   may return true.
Too late, the damage is already done.
http://slobodanblazeski.blogspot.com/2009/09/hyperspec-treasure-pathname-match-p.html

Bobi
http://www.linkedin.com/in/slobodanblazeski

0 new messages