220 lines
11 KiB
HTML
220 lines
11 KiB
HTML
|
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
|
||
|
<!Converted with LaTeX2HTML 0.6.5 (Tue Nov 15 1994) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
|
||
|
<HEAD>
|
||
|
<TITLE>14.4. Searching Sequences for Items</TITLE>
|
||
|
</HEAD>
|
||
|
<BODY>
|
||
|
<meta name="description" value=" Searching Sequences for Items">
|
||
|
<meta name="keywords" value="clm">
|
||
|
<meta name="resource-type" value="document">
|
||
|
<meta name="distribution" value="global">
|
||
|
<P>
|
||
|
<b>Common Lisp the Language, 2nd Edition</b>
|
||
|
<BR> <HR><A NAME=tex2html3337 HREF="node146.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3335 HREF="node141.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3329 HREF="node144.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3339 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3340 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html3338 HREF="node146.html"> Sorting and Merging</A>
|
||
|
<B>Up:</B> <A NAME=tex2html3336 HREF="node141.html"> Sequences</A>
|
||
|
<B> Previous:</B> <A NAME=tex2html3330 HREF="node144.html"> Modifying Sequences</A>
|
||
|
<HR> <P>
|
||
|
<H1><A NAME=SECTION001840000000000000000>14.4. Searching Sequences for Items</A></H1>
|
||
|
<P>
|
||
|
Each of these functions searches a sequence to locate one or more
|
||
|
elements satisfying some test.
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<pre>
|
||
|
<tt>find <i>item</i> <i>sequence</i> &key :from-end :test :test-not :start :end :key
|
||
|
find-if <i>predicate</i> <i>sequence</i> &key :from-end :start :end :key
|
||
|
find-if-not <i>predicate</i> <i>sequence</i> &key :from-end :start :end :key</tt>
|
||
|
</pre>
|
||
|
<P>
|
||
|
If the <i>sequence</i> contains an element satisfying the test,
|
||
|
then the leftmost such element
|
||
|
is returned; otherwise <tt>nil</tt> is returned.
|
||
|
<P>
|
||
|
If <tt>:start</tt> and <tt>:end</tt> keyword arguments are given,
|
||
|
only the specified subsequence of <i>sequence</i> is searched.
|
||
|
<P>
|
||
|
If a non-<tt>nil :from-end</tt> keyword argument is specified, then the result is
|
||
|
the <i>rightmost</i> element satisfying the test.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=15926> </A>
|
||
|
to restrict user side effects; see section <A HREF="node92.html#STRUCTURETRAVERSALSECTION">7.9</A>.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<pre>
|
||
|
<tt>position <i>item</i> <i>sequence</i> &key :from-end :test :test-not
|
||
|
:start :end :key
|
||
|
position-if <i>predicate</i> <i>sequence</i> &key :from-end
|
||
|
:start :end :key
|
||
|
position-if-not <i>predicate</i> <i>sequence</i> &key :from-end
|
||
|
:start :end :key</tt>
|
||
|
</pre>
|
||
|
<P>If the <i>sequence</i> contains an element satisfying the test,
|
||
|
then the index within the sequence of the leftmost such element
|
||
|
is returned as a non-negative integer; otherwise <tt>nil</tt> is returned.
|
||
|
<P>
|
||
|
If <tt>:start</tt> and <tt>:end</tt> keyword arguments are given,
|
||
|
only the specified subsequence of <i>sequence</i> is searched.
|
||
|
However, the index returned is relative to the entire sequence,
|
||
|
not to the subsequence.
|
||
|
<P>
|
||
|
If a non-<tt>nil :from-end</tt> keyword argument is specified, then the result is
|
||
|
the index of the <i>rightmost</i> element satisfying the test. (The index
|
||
|
returned, however, is an index from the left-hand end, as usual.)
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=15940> </A>
|
||
|
to restrict user side effects; see section <A HREF="node92.html#STRUCTURETRAVERSALSECTION">7.9</A>.
|
||
|
<P>
|
||
|
Here is a simple piece of code that uses several of the sequence
|
||
|
functions, notably <tt>position-if</tt> and <tt>find-if</tt>,
|
||
|
to process strings. Note one use of <tt>loop</tt> as well.
|
||
|
<P><pre>
|
||
|
(defun debug-palindrome (s)
|
||
|
(flet ((match (x) (char-equal (first x) (third x))))
|
||
|
(let* ((pairs (loop for c across s
|
||
|
for j from 0
|
||
|
when (alpha-char-p c)
|
||
|
collect (list c j)))
|
||
|
(quads (mapcar #'append pairs (reverse pairs)))
|
||
|
(diffpos (position-if (complement #'match) quads)))
|
||
|
(when diffpos
|
||
|
(let* ((diff (elt quads diffpos))
|
||
|
(same (find-if #'match quads
|
||
|
:start (+ diffpos 1))))
|
||
|
(if same
|
||
|
(format nil
|
||
|
"/~A/ (at ~D) is not the reverse of /~A/"
|
||
|
(subseq s (second diff) (second same))
|
||
|
(second diff)
|
||
|
(subseq s (+ (fourth same) 1)
|
||
|
(+ (fourth diff) 1)))
|
||
|
"This palindrome is completely messed up!"))))))
|
||
|
</pre><P>
|
||
|
Here is an example of its behavior.
|
||
|
<P><pre>
|
||
|
(setq panama ;A putative palindrome?
|
||
|
"A man, a plan, a canoe, pasta, heros, rajahs,
|
||
|
a coloratura, maps, waste, percale, macaroni, a gag,
|
||
|
a banana bag, a tan, a tag, a banana bag again
|
||
|
(or a camel), a crepe, pins, Spam, a rut, a Rolo,
|
||
|
cash, a jar, sore hats, a peon, a canal-Panama!")
|
||
|
</pre><P>
|
||
|
<P><pre>
|
||
|
(debug-palindrome panama)
|
||
|
=> "/wast/ (at 73) is not the reverse of /, pins/"
|
||
|
|
||
|
(replace panama "snipe" :start1 73) ;Repair it
|
||
|
=> "A man, a plan, a canoe, pasta, heros, rajahs,
|
||
|
a coloratura, maps, snipe, percale, macaroni, a gag,
|
||
|
a banana bag, a tan, a tag, a banana bag again
|
||
|
(or a camel), a crepe, pins, Spam, a rut, a Rolo,
|
||
|
cash, a jar, sore hats, a peon, a canal-Panama!"
|
||
|
|
||
|
(debug-palindrome panama) => nil ;Copacetic-a true palindrome
|
||
|
|
||
|
(debug-palindrome "Rubber baby buggy bumpers")
|
||
|
=> "/Rubber / (at 0) is not the reverse of /umpers/"
|
||
|
|
||
|
(debug-palindrome "Common Lisp: The Language")
|
||
|
=> "/Commo/ (at 0) is not the reverse of /guage/"
|
||
|
|
||
|
(debug-palindrome "Complete mismatches are hard to find")
|
||
|
=>
|
||
|
"/Complete mism/ (at 0) is not the reverse of /re hard to find/"
|
||
|
|
||
|
(debug-palindrome "Waltz, nymph, for quick jigs vex Bud")
|
||
|
=> "This palindrome is completely messed up!"
|
||
|
|
||
|
(debug-palindrome "Doc, note: I dissent. A fast never
|
||
|
prevents a fatness. I diet on cod.")
|
||
|
=><tt>nil</tt> ;Another winner
|
||
|
|
||
|
(debug-palindrome "Top step's pup's pet spot") => nil
|
||
|
</pre><P>
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<pre>
|
||
|
<tt>count <i>item</i> <i>sequence</i> &key :from-end :test :test-not :start :end :key
|
||
|
count-if <i>predicate</i> <i>sequence</i> &key :from-end :start :end :key
|
||
|
count-if-not <i>predicate</i> <i>sequence</i> &key :from-end :start :end :key</tt>
|
||
|
</pre>
|
||
|
<P>The result is always a non-negative integer, the number of
|
||
|
elements in the specified subsequence of <i>sequence</i> satisfying
|
||
|
the test.
|
||
|
<P>
|
||
|
The <tt>:from-end</tt> argument does not affect the result returned;
|
||
|
it is accepted purely for compatibility with other sequence functions.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=15966> </A>
|
||
|
to restrict user side effects; see section <A HREF="node92.html#STRUCTURETRAVERSALSECTION">7.9</A>.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>mismatch <i>sequence1</i> <i>sequence2</i> &key :from-end :test :test-not :key :start1 :start2 :end1 :end2</tt><P>The specified subsequences of
|
||
|
<i>sequence1</i> and <i>sequence2</i> are compared element-wise.
|
||
|
If they are of equal length and match in every element, the result is
|
||
|
<tt>nil</tt>. Otherwise, the result is a non-negative integer.
|
||
|
This result is the index within
|
||
|
<i>sequence1</i> of the leftmost position at which the two
|
||
|
subsequences fail to match; or,
|
||
|
if one subsequence is shorter than and a matching prefix of the other,
|
||
|
the result is the index
|
||
|
relative to <i>sequence1</i> beyond the last position tested.
|
||
|
<P>
|
||
|
If a non-<tt>nil :from-end</tt> keyword argument is given, then
|
||
|
<i>one plus</i> the index of the <i>rightmost</i>
|
||
|
position in which the sequences differ is returned. In effect, the (sub)sequences
|
||
|
are aligned at their right-hand ends; then, the last elements are compared,
|
||
|
the penultimate elements, and so on. The index returned is again
|
||
|
an index relative to <i>sequence1</i>.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=15982> </A>
|
||
|
to restrict user side effects; see section <A HREF="node92.html#STRUCTURETRAVERSALSECTION">7.9</A>.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>search <i>sequence1</i> <i>sequence2</i> &key :from-end :test :test-not :key :start1 :start2 :end1 :end2</tt><P>A search is conducted for a subsequence of <i>sequence2</i> that
|
||
|
element-wise matches <i>sequence1</i>.
|
||
|
If there is no such subsequence, the result is <tt>nil</tt>; if there is,
|
||
|
the result is the index into <i>sequence2</i> of the leftmost element
|
||
|
of the leftmost such matching subsequence.
|
||
|
<P>
|
||
|
If a non-<tt>nil :from-end</tt> keyword argument is given,
|
||
|
the index of the leftmost
|
||
|
element of the <i>rightmost</i> matching subsequence is returned.
|
||
|
<P>
|
||
|
The implementation may choose to search the sequence in any order;
|
||
|
there is no guarantee on the number of times the test is made.
|
||
|
For example, <tt>search</tt> with a non-<tt>nil :from-end</tt>
|
||
|
argument might actually search a list from left to right
|
||
|
instead of from right to left (but in either case would return
|
||
|
the rightmost matching subsequence, of course). Therefore it is a good
|
||
|
idea for a user-supplied predicate to be free of side effects.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=15998> </A>
|
||
|
to restrict user side effects; see section <A HREF="node92.html#STRUCTURETRAVERSALSECTION">7.9</A>.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR> <HR><A NAME=tex2html3337 HREF="node146.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3335 HREF="node141.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3329 HREF="node144.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3339 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3340 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html3338 HREF="node146.html"> Sorting and Merging</A>
|
||
|
<B>Up:</B> <A NAME=tex2html3336 HREF="node141.html"> Sequences</A>
|
||
|
<B> Previous:</B> <A NAME=tex2html3330 HREF="node144.html"> Modifying Sequences</A>
|
||
|
<HR> <P>
|
||
|
<HR>
|
||
|
<P><ADDRESS>
|
||
|
AI.Repository@cs.cmu.edu
|
||
|
</ADDRESS>
|
||
|
</BODY>
|