330 lines
17 KiB
HTML
330 lines
17 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>15.5. Using Lists as Sets</TITLE>
|
||
|
</HEAD>
|
||
|
<BODY>
|
||
|
<meta name="description" value=" Using Lists as Sets">
|
||
|
<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=tex2html3425 HREF="node153.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3423 HREF="node147.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3417 HREF="node151.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3427 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3428 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html3426 HREF="node153.html"> Association Lists</A>
|
||
|
<B>Up:</B> <A NAME=tex2html3424 HREF="node147.html"> Lists</A>
|
||
|
<B> Previous:</B> <A NAME=tex2html3418 HREF="node151.html"> Substitution of Expressions</A>
|
||
|
<HR> <P>
|
||
|
<H1><A NAME=SECTION001950000000000000000>15.5. Using Lists as Sets</A></H1>
|
||
|
<P>
|
||
|
Common Lisp includes functions that allow a list of items to be
|
||
|
treated as a <i>set</i>.
|
||
|
There are functions to add, remove, and search for items in a list,
|
||
|
based on various criteria.
|
||
|
There are also set union, intersection, and difference functions.
|
||
|
<P>
|
||
|
The naming conventions for these functions and for their keyword
|
||
|
arguments generally follow the conventions that apply to the generic sequence
|
||
|
functions. See chapter <A HREF="node141.html#KSEQUE">14</A>.
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>member <i>item</i> <i>list</i> &key :test :test-not :key <BR></tt><tt>member-if <i>predicate</i> <i>list</i> &key :key <BR></tt><tt>member-if-not <i>predicate</i> <i>list</i> &key :key</tt><P>The <i>list</i> is searched for an element that satisfies the test.
|
||
|
If none is found, <tt>nil</tt> is returned;
|
||
|
otherwise, the tail of <i>list</i> beginning
|
||
|
with the first element that satisfied the test is returned.
|
||
|
The <i>list</i> is searched on the top level only.
|
||
|
These functions are suitable for use as predicates.
|
||
|
<P>
|
||
|
For example:
|
||
|
<P><pre>
|
||
|
(member 'snerd '(a b c d)) => <tt>nil</tt>
|
||
|
(member-if #'numberp '(a #\Space 5/3 foo)) => (5/3 foo)
|
||
|
(member 'a '(g (a y) c a d e a f)) => (a d e a f)
|
||
|
</pre><P>
|
||
|
Note, in the last example,
|
||
|
that the value returned by <tt>member</tt> is <tt>eq</tt> to the portion of the list
|
||
|
beginning with <tt>a</tt>.
|
||
|
Thus <tt>rplaca</tt> on the result of <tt>member</tt> may be used
|
||
|
to alter the found list element,
|
||
|
if a check is first made that <tt>member</tt> did not return <tt>nil</tt>.
|
||
|
<P>
|
||
|
See also <tt>find</tt> and <tt>position</tt>.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=16883> </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>
|
||
|
<hr>
|
||
|
<b>Compatibility note:</b> In MacLisp, the <tt>member</tt> function uses
|
||
|
an <tt>equal</tt> comparison rather than <tt>eql</tt>, which is the default
|
||
|
test for <tt>member</tt> in Common Lisp. Where in MacLisp one would write
|
||
|
<tt>(member x y)</tt>, in Common Lisp one must write <tt>(member x y :test #'equal)</tt>
|
||
|
to get a completely identical effect. Similarly, one can get the
|
||
|
precise effect, and no more, of the MacLisp <tt>(memq x y)</tt>
|
||
|
by writing in Common Lisp <tt>(member x y :test #'eq)</tt>.
|
||
|
<hr>
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>tailp <i>sublist</i> <i>list</i></tt><P>This predicate is true if <i>sublist</i> is a sublist of <i>list</i> (that is,
|
||
|
one of the conses that makes up <i>list</i>); otherwise it is false.
|
||
|
Another way to look at this is that <tt>tailp</tt> is true if
|
||
|
<tt>(nthcdr <i>n</i> <i>list</i>)</tt> is <i>sublist</i>, for some value of <i>n</i>.
|
||
|
See <tt>ldiff</tt>.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(TAILP-NIL) <A NAME=16908> </A>
|
||
|
to strike the parenthetical remark that suggests
|
||
|
that the <i>sublist</i> must be a cons, to clarify that <tt>tailp</tt>
|
||
|
is true if and only if there exists an integer <i>n</i> such that
|
||
|
<P><pre>
|
||
|
(eql <i>sublist</i> (nthcdr <i>n</i> <i>list</i>))
|
||
|
</pre><P>
|
||
|
and to specify that <i>list</i> may be a dotted list (implying that
|
||
|
implementations must use <tt>atom</tt> and not <tt>endp</tt> to check for
|
||
|
the end of the <i>list</i>).
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>adjoin <i>item</i> <i>list</i> &key :test :test-not :key</tt><P><tt>adjoin</tt> is used to add an element to a set, provided that
|
||
|
it is not already a member. The equality test defaults to <tt>eql</tt>.
|
||
|
<P><pre>
|
||
|
(adjoin <i>item</i> <i>list</i>) == (if (member <i>item</i> <i>list</i>) <i>list</i> (cons <i>item</i> <i>list</i>))
|
||
|
</pre><P>
|
||
|
In general, the test may be any predicate; the <i>item</i> is added to the
|
||
|
list only if there is no element of the list that ``satisfies the test.''
|
||
|
<P>
|
||
|
<tt>adjoin</tt> deviates from the usual rules described in chapter <A HREF="node141.html#KSEQUE">14</A>
|
||
|
for the treatment of arguments named <i>item</i> and <tt>:key</tt>.
|
||
|
If a <tt>:key</tt> function is specified, it is applied to <i>item</i>
|
||
|
as well as to each element of the list. The rationale is that
|
||
|
if the <i>item</i> is not yet in the list, it soon will be, and so
|
||
|
the test is more properly viewed as being between two elements
|
||
|
rather than between a separate <i>item</i> and an element.
|
||
|
<P><pre>
|
||
|
(adjoin <i>item</i> <i>list</i> :key <i>fn</i>)
|
||
|
== (if (member (funcall <i>fn</i> <i>item</i>) <i>list</i>
|
||
|
</pre><P>
|
||
|
See <tt>pushnew</tt>.
|
||
|
<p>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
<i>Notice of correction.</i>
|
||
|
In the first edition, the form <tt>(<i>fn</i> <i>item</i>)</tt> appeared
|
||
|
in this example without the required <tt>funcall</tt>.
|
||
|
<P>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=16964> </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>union <i>list1</i> <i>list2</i> &key :test :test-not :key <BR></tt><tt>nunion <i>list1</i> <i>list2</i> &key :test :test-not :key</tt><P><tt>union</tt> takes two lists and returns a new list containing
|
||
|
everything that is an element of either of the <i>lists</i>.
|
||
|
If there is a duplication between two lists,
|
||
|
only one of the duplicate instances will be in the result.
|
||
|
If either of the arguments has duplicate entries within it,
|
||
|
the redundant entries
|
||
|
may or may not appear in the result.
|
||
|
For example:
|
||
|
<P><pre>
|
||
|
(union '(a b c) '(f a d))
|
||
|
=> (a b c f d) or (b c f a d) or (d f a b c) or ...
|
||
|
|
||
|
(union '((x 5) (y 6)) '((z 2) (x 4)) :key #'car)
|
||
|
=> ((x 5) (y 6) (z 2)) or ((x 4) (y 6) (z 2)) or ...
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
There is no guarantee that the order of elements in the result will
|
||
|
reflect the ordering of the arguments in any particular way.
|
||
|
The implementation is therefore free to use any of a variety of strategies.
|
||
|
The result list may share cells with, or be <tt>eq</tt> to, either of the arguments
|
||
|
if appropriate.
|
||
|
<P>
|
||
|
In general, the test may be any predicate, and the union operation may be
|
||
|
described as follows. For all possible ordered pairs consisting of one
|
||
|
element from <i>list1</i> and one element from <i>list2</i>, the test is used
|
||
|
to determine whether they ``match.'' For every matching pair, at least
|
||
|
one of the two elements of the pair will be in the result. Moreover, any
|
||
|
element from either list that matches no element of the other will appear
|
||
|
in the result. All this is very general, but probably not particularly
|
||
|
useful unless the test is an equivalence relation.
|
||
|
<P>
|
||
|
The <tt>:test-not</tt> argument can be useful when the test function
|
||
|
is the logical negation of an equivalence test. A good example
|
||
|
of this is the function <tt>mismatch</tt>, which is logically inverted
|
||
|
so that possibly useful information can be returned if the arguments do not
|
||
|
match. This additional ``useful information'' is discarded in the following
|
||
|
example; <tt>mismatch</tt> is used purely as a predicate.
|
||
|
<P><pre>
|
||
|
(union '(#(a b) #(5 0 6) #(f 3))
|
||
|
'(#(5 0 6) (a b) #(g h))
|
||
|
:test-not
|
||
|
#'mismatch)
|
||
|
=> (#(a b) #(5 0 6) #(f 3) #(g h)) ;One possible result
|
||
|
=> ((a b) #(f 3) #(5 0 6) #(g h)) ;Another possible result
|
||
|
</pre><P>
|
||
|
Using <tt><tt>:test-not</tt> #'mismatch</tt> differs from using
|
||
|
<tt><tt>:test</tt> #'equalp</tt>, for example, because <tt>mismatch</tt>
|
||
|
will determine that <tt>#(a b)</tt> and <tt>(a b)</tt> are the same,
|
||
|
while <tt>equalp</tt> would regard them as not the same.
|
||
|
<P>
|
||
|
<tt>nunion</tt> is the destructive version of <tt>union</tt>.
|
||
|
It performs the same operation but may destroy the argument lists,
|
||
|
perhaps in order to use their cells to construct the result.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=16997> </A>
|
||
|
to restrict user side effects; see section <A HREF="node92.html#STRUCTURETRAVERSALSECTION">7.9</A>.
|
||
|
<P>
|
||
|
X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) <A NAME=17001> </A>
|
||
|
to clarify the permissible side effects of certain operations;
|
||
|
<tt>nunion</tt> is permitted to perform a <tt>setf</tt> on any part,
|
||
|
<i>car</i> or <i>cdr</i>, of the top-level list structure of
|
||
|
any of the argument lists.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>intersection <i>list1</i> <i>list2</i> &key :test :test-not :key <BR></tt><tt>nintersection <i>list1</i> <i>list2</i> &key :test :test-not :key</tt><P><tt>intersection</tt> takes two lists and returns a new list containing
|
||
|
everything that is an element of both argument lists.
|
||
|
If either list has duplicate entries, the redundant entries
|
||
|
may or may not appear in the result.
|
||
|
For example:
|
||
|
<P><pre>
|
||
|
(intersection '(a b c) '(f a d)) => (a)
|
||
|
</pre><P>
|
||
|
There is no guarantee that the order of elements in the result will
|
||
|
reflect the ordering of the arguments in any particular way.
|
||
|
The implementation is therefore free to use any of a variety of strategies.
|
||
|
The result list may share cells with, or be <tt>eq</tt> to, either of the arguments
|
||
|
if appropriate.
|
||
|
<P>
|
||
|
In general, the test may be any predicate, and the intersection operation
|
||
|
may be described as follows. For all possible ordered pairs consisting of
|
||
|
one element from <i>list1</i> and one element from <i>list2</i>, the test is
|
||
|
used to determine whether they ``match.'' For every matching pair,
|
||
|
exactly one of the two elements of the pair will be put in the result.
|
||
|
No element from either list appears in the result that does not match
|
||
|
an element from the other list.
|
||
|
All this is very general, but probably
|
||
|
not particularly useful unless the test is an equivalence relation.
|
||
|
<P>
|
||
|
<tt>nintersection</tt> is the destructive version of <tt>intersection</tt>.
|
||
|
It performs the same operation, but may destroy <i>list1</i>,
|
||
|
perhaps in order to use its cells to construct the result.
|
||
|
(The argument <i>list2</i> is <i>not</i> destroyed.)
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=17021> </A>
|
||
|
to restrict user side effects; see section <A HREF="node92.html#STRUCTURETRAVERSALSECTION">7.9</A>.
|
||
|
<P>
|
||
|
X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) <A NAME=17025> </A>
|
||
|
to clarify the permissible side effects of certain operations;
|
||
|
<tt>nintersection</tt> is permitted to perform a <tt>setf</tt> on any part,
|
||
|
<i>car</i> or <i>cdr</i>, of the top-level list structure of
|
||
|
any of the argument lists.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>set-difference <i>list1</i> <i>list2</i> &key :test :test-not :key <BR></tt><tt>nset-difference <i>list1</i> <i>list2</i> &key :test :test-not :key</tt><P><tt>set-difference</tt> returns a list of elements of <i>list1</i>
|
||
|
that do not appear in <i>list2</i>. This operation is
|
||
|
not destructive.
|
||
|
<P>
|
||
|
There is no guarantee that the order of elements in the result will
|
||
|
reflect the ordering of the arguments in any particular way.
|
||
|
The implementation is therefore free to use any of a variety of strategies.
|
||
|
The result list may share cells with, or be <tt>eq</tt> to, either of the arguments
|
||
|
if appropriate.
|
||
|
<P>
|
||
|
In general, the test may be any predicate, and the set difference operation
|
||
|
may be described as follows. For all possible ordered pairs consisting of
|
||
|
one element from <i>list1</i> and one element from <i>list2</i>, the test is
|
||
|
used to determine whether they ``match.'' An element of <i>list1</i>
|
||
|
appears in the result if and only if it does not match any element
|
||
|
of <i>list2</i>. This is very general and permits interesting applications.
|
||
|
For example, one can remove from a list of strings all those strings
|
||
|
containing one of a given list of characters:
|
||
|
<P><pre>
|
||
|
;; Remove all flavor names that contain "c" or "w".
|
||
|
(set-difference '("strawberry" "chocolate" "banana"
|
||
|
"lemon" "pistachio" "rhubarb")
|
||
|
'(#\c #\w)
|
||
|
:test
|
||
|
#'(lambda (s c) (find c s)))
|
||
|
=> ("banana" "rhubarb" "lemon") ;One possible ordering
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
<tt>nset-difference</tt> is the destructive version of <tt>set-difference</tt>.
|
||
|
This operation may destroy <i>list1</i>.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=17050> </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>
|
||
|
<hr>
|
||
|
<b>Compatibility note:</b> An approximately equivalent Interlisp function
|
||
|
is <tt>ldifference</tt>.
|
||
|
<hr>
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<pre>
|
||
|
set-exclusive-or <i>list1</i> <i>list2</i> &key :test :test-not :key
|
||
|
nset-exclusive-or <i>list1</i> <i>list2</i> &key :test :test-not :key
|
||
|
</pre>
|
||
|
<P><tt>set-exclusive-or</tt> returns a list of elements that appear
|
||
|
in exactly one of <i>list1</i> and <i>list2</i>.
|
||
|
This operation is not destructive.
|
||
|
<P>
|
||
|
There is no guarantee that the order of elements in the result will
|
||
|
reflect the ordering of the arguments in any particular way.
|
||
|
The implementation is therefore free to use any of a variety of strategies.
|
||
|
The result list may share cells with, or be <tt>eq</tt> to, either of the arguments
|
||
|
if appropriate.
|
||
|
<P>
|
||
|
In general, the test may be any predicate, and the set-exclusive-or operation
|
||
|
may be described as follows. For all possible ordered pairs consisting of
|
||
|
one element from <i>list1</i> and one element from <i>list2</i>, the test is
|
||
|
used to determine whether they ``match.'' The result contains precisely
|
||
|
those elements of <i>list1</i> and <i>list2</i> that appear in no matching pair.
|
||
|
<P>
|
||
|
<tt>nset-exclusive-or</tt> is the destructive version of <tt>set-exclusive-or</tt>.
|
||
|
Both lists may be destroyed in producing the result.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=17069> </A>
|
||
|
to restrict user side effects; see section <A HREF="node92.html#STRUCTURETRAVERSALSECTION">7.9</A>.
|
||
|
<P>
|
||
|
X3J13 voted in March 1989 (REMF-DESTRUCTION-UNSPECIFIED) <A NAME=17073> </A>
|
||
|
to clarify the permissible side effects of certain operations;
|
||
|
<tt>nset-exclusive-or</tt> is permitted to perform a <tt>setf</tt> on any part,
|
||
|
<i>car</i> or <i>cdr</i>, of the top-level list structure of
|
||
|
any of the argument lists.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR><b>[Function]</b><BR>
|
||
|
<tt>subsetp <i>list1</i> <i>list2</i> &key :test :test-not :key</tt><P><tt>subsetp</tt> is a predicate that is true if every element of <i>list1</i>
|
||
|
appears in (``matches'' some element of) <i>list2</i>, and false otherwise.
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
X3J13 voted in January 1989
|
||
|
(MAPPING-DESTRUCTIVE-INTERACTION) <A NAME=17085> </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=tex2html3425 HREF="node153.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html3423 HREF="node147.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html3417 HREF="node151.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html3427 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html3428 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html3426 HREF="node153.html"> Association Lists</A>
|
||
|
<B>Up:</B> <A NAME=tex2html3424 HREF="node147.html"> Lists</A>
|
||
|
<B> Previous:</B> <A NAME=tex2html3418 HREF="node151.html"> Substitution of Expressions</A>
|
||
|
<HR> <P>
|
||
|
<HR>
|
||
|
<P><ADDRESS>
|
||
|
AI.Repository@cs.cmu.edu
|
||
|
</ADDRESS>
|
||
|
</BODY>
|