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
> 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__
> 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
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__
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
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
> 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__
And one of us thought he better check with the analyst.
kt
--
http://thelaughingstockatpngs.com/
http://www.facebook.com/pages/The-Laughingstock/115923141782?ref=nf
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
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>
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?"
Thanks for the tip mismatch is better then subseq but string-equal is
just what I need.
Bobi
cheers
Bobi
REMOVE-IF-NOT is KEEP-IF; (KEEP ...) would be (REMOVE ... :TEST-NOT #'EQL),
or (REMOVE ... :TEST (COMPLEMENT #'EQL)) if someone insists.
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.
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
(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
Bobi
> 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.