1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-25 04:40:19 +02:00

(SRFI-1 Set Operations): Revise and expand.

(SRFI-1 Deleting): In delete, cross reference lset-difference.
This commit is contained in:
Kevin Ryde 2005-04-01 23:17:21 +00:00
parent 2f60df3b78
commit 4eb21177ee

View file

@ -872,8 +872,6 @@ This version of @code{member} extends the core @code{member}
@subsubsection Deleting @subsubsection Deleting
@cindex list delete @cindex list delete
@c FIXME::martin: Review me!
@deffn {Scheme Procedure} delete x lst [=] @deffn {Scheme Procedure} delete x lst [=]
@deffnx {Scheme Procedure} delete! x lst [=] @deffnx {Scheme Procedure} delete! x lst [=]
Return a list containing the elements of @var{lst} but with those Return a list containing the elements of @var{lst} but with those
@ -892,8 +890,10 @@ deleted with @code{(delete 5 lst <)}.
common tail with @var{lst}. @code{delete!} may modify the structure common tail with @var{lst}. @code{delete!} may modify the structure
of @var{lst} to construct its return. of @var{lst} to construct its return.
These functions extend the core @code{delete} and @code{delete!} in These functions extend the core @code{delete} and @code{delete!}
accepting an equality predicate. (@pxref{List Modification}) (@pxref{List Modification}) in accepting an equality predicate. See
also @code{lset-difference} (@pxref{SRFI-1 Set Operations}) for
deleting multiple elements from a list.
@end deffn @end deffn
@deffn {Scheme Procedure} delete-duplicates lst [=] @deffn {Scheme Procedure} delete-duplicates lst [=]
@ -981,81 +981,198 @@ the list structure of @var{alist} to construct its return.
@subsubsection Set Operations on Lists @subsubsection Set Operations on Lists
@cindex list set operation @cindex list set operation
@c FIXME::martin: Review me! Lists can be used to represent sets of objects. The procedures in
this section operate on such lists as sets.
Lists can be used for representing sets of objects. The procedures Note that lists are not an efficient way to implement large sets. The
documented in this section can be used for such set representations. procedures here typically take time @math{@var{m}@times{}@var{n}} when
Man combining several sets or adding elements, they make sure that no operating on @var{m} and @var{n} element lists. Other data structures
object is contained more than once in a given list. Please note that like trees, bitsets (@pxref{Bit Vectors}) or hash tables (@pxref{Hash
lists are not a too efficient implementation method for sets, so if Tables}) are faster.
you need high performance, you should think about implementing a
custom data structure for representing sets, such as trees, bitsets,
hash tables or something similar.
All these procedures accept an equality predicate as the first All these procedures take an equality predicate as the first argument.
argument. This predicate is used for testing the objects in the list This predicate is used for testing the objects in the list sets for
sets for sameness. sameness. This predicate must be consistent with @code{eq?}
(@pxref{Equality}) in the sense that if two list elements are
@code{eq?} then they must also be equal under the predicate. This
simply means a given object must be equal to itself.
@deffn {Scheme Procedure} lset<= = list1 @dots{} @deffn {Scheme Procedure} lset<= = list1 list2 @dots{}
Return @code{#t} if every @var{listi} is a subset of @var{listi+1}, Return @code{#t} if each list is a subset of the one following it.
otherwise return @code{#f}. Returns @code{#t} if called with less Ie.@: @var{list1} a subset of @var{list2}, @var{list2} a subset of
than two arguments. @var{=} is used for testing element equality. @var{list3}, etc, for as many lists as given. If only one list or no
lists are given then the return is @code{#t}.
A list @var{x} is a subset of @var{y} if each element of @var{x} is
equal to some element in @var{y}. Elements are compared using the
given @var{=} procedure, called as @code{(@var{=} xelem yelem)}.
@example
(lset<= eq?) @result{} #t
(lset<= eqv? '(1 2 3) '(1)) @result{} #f
(lset<= eqv? '(1 3 2) '(4 3 1 2)) @result{} #t
@end example
@end deffn @end deffn
@deffn {Scheme Procedure} lset= = list1 list2 @dots{} @deffn {Scheme Procedure} lset= = list1 list2 @dots{}
Return @code{#t} if all argument lists are equal. @var{=} is used for Return @code{#t} if all argument lists are set-equal. @var{list1} is
testing element equality. compared to @var{list2}, @var{list2} to @var{list3}, etc, for as many
lists as given. If only one list or no lists are given then the
return is @code{#t}.
Two lists @var{x} and @var{y} are set-equal if each element of @var{x}
is equal to some element of @var{y} and conversely each element of
@var{y} is equal to some element of @var{x}. The order of the
elements in the lists doesn't matter. Element equality is determined
with the given @var{=} procedure, called as @code{(@var{=} xelem
yelem)}, but exactly which calls are made is unspecified.
@example
(lset= eq?) @result{} #t
(lset= eqv? '(1 2 3) '(3 2 1)) @result{} #t
(lset= string-ci=? '("a" "A" "b") '("B" "b" "a")) @result{} #t
@end example
@end deffn @end deffn
@deffn {Scheme Procedure} lset-adjoin = list elt1 @dots{} @deffn {Scheme Procedure} lset-adjoin = list elem1 @dots{}
Add all @var{elts} to the list @var{list}, suppressing duplicates and Add to @var{list} any of the given @var{elem}s not already in the
return the resulting list. @var{=} is used for testing list. @var{elem}s are @code{cons}ed onto the start of @var{list} (so
element equality. the return shares a common tail with @var{list}), but the order
they're added is unspecified.
The given @var{=} procedure is used for comparing elements, called as
@code{(@var{=} listelem elem)}, ie.@: the second argument is one of
the given @var{elem} parameters.
@example
(lset-adjoin eqv? '(1 2 3) 4 1 5) @result{} (5 4 1 2 3)
@end example
@end deffn @end deffn
@deffn {Scheme Procedure} lset-union = list1 @dots{} @deffn {Scheme Procedure} lset-union = list1 list2 @dots{}
@deffnx {Scheme Procedure} lset-union! = list1 @dots{} @deffnx {Scheme Procedure} lset-union! = list1 list2 @dots{}
Return the union of all argument list sets. The union is the set of Return the union of the argument list sets. The result is built by
all elements which appear in any of the argument sets. taking the union of @var{list1} and @var{list2}, then the union of
@code{lset-union!} is allowed, but not required to modify its first that with @var{list3}, etc, for as many lists as given. For one list
argument. @var{=} is used for testing element equality. argument that list itself is the result, for no list arguments the
result is the empty list.
The union of two lists @var{x} and @var{y} is formed as follows. If
@var{x} is empty then the result is @var{y}. Otherwise start with
@var{x} as the result and consider each @var{y} element (from first to
last). A @var{y} element not equal to something already in the result
is @code{cons}ed onto the result.
The given @var{=} procedure is used for comparing elements, called as
@code{(@var{=} relem yelem)}. The first argument is from the result
accumulated so far, and the second is from the list being union-ed in.
But exactly which calls are made is otherwise unspecified.
Notice that duplicate elements in @var{list1} (or the first non-empty
list) are preserved, but that repeated elements in subsequent lists
are only added once.
@example
(lset-union eqv?) @result{} ()
(lset-union eqv? '(1 2 3)) @result{} (1 2 3)
(lset-union eqv? '(1 2 1 3) '(2 4 5) '(5)) @result{} (5 4 1 2 1 3)
@end example
@code{lset-union} doesn't change the given lists but the result may
share a tail with the first non-empty list. @code{lset-union!} can
modify all of the given lists to form the result.
@end deffn @end deffn
@deffn {Scheme Procedure} lset-intersection = list1 list2 @dots{} @deffn {Scheme Procedure} lset-intersection = list1 list2 @dots{}
@deffnx {Scheme Procedure} lset-intersection! = list1 list2 @dots{} @deffnx {Scheme Procedure} lset-intersection! = list1 list2 @dots{}
Return the intersection of all argument list sets. The intersection Return the intersection of @var{list1} with the other argument lists,
is the set containing all elements which appear in all argument sets. meaning those elements of @var{list1} which are also in all of
@code{lset-intersection!} is allowed, but not required to modify its @var{list2} etc. For one list argument, just that list is returned.
first argument. @var{=} is used for testing element equality.
The test for an element of @var{list1} to be in the return is simply
that it's equal to some element in each of @var{list2} etc. Notice
this means an element appearing twice in @var{list1} but only once in
each of @var{list2} etc will go into the return twice. The return has
its elements in the same order as they were in @var{list1}.
The given @var{=} procedure is used for comparing elements, called as
@code{(@var{=} elem1 elemN)}. The first argument is from @var{list1}
and the second is from one of the subsequent lists. But exactly which
calls are made and in what order is unspecified.
@example
(lset-intersection eqv? '(x y)) @result{} (x y)
(lset-intersection eqv? '(1 2 3) '(4 3 2)) @result{} (2 3)
(lset-intersection eqv? '(1 1 2 2) '(1 2) '(2 1) '(2)) @result{} (2 2)
@end example
The return from @code{lset-intersection} may share a tail with
@var{list1}. @code{lset-intersection!} may modify @var{list1} to form
its result.
@end deffn @end deffn
@deffn {Scheme Procedure} lset-difference = list1 list2 @dots{} @deffn {Scheme Procedure} lset-difference = list1 list2 @dots{}
@deffnx {Scheme Procedure} lset-difference! = list1 list2 @dots{} @deffnx {Scheme Procedure} lset-difference! = list1 list2 @dots{}
Return the difference of all argument list sets. The difference is Return @var{list1} with any elements in @var{list2}, @var{list3} etc
the the set containing all elements of the first list which do not removed (ie.@: subtracted). For one list argument, just that list is
appear in the other lists. @code{lset-difference!} is allowed, but returned.
not required to modify its first argument. @var{=} is used for testing
element equality.
@end deffn
@deffn {Scheme Procedure} lset-xor = list1 @dots{} The given @var{=} procedure is used for comparing elements, called as
@deffnx {Scheme Procedure} lset-xor! = list1 @dots{} @code{(@var{=} elem1 elemN)}. The first argument is from @var{list1}
Return the set containing all elements which appear in the first and the second from one of the subsequent lists. But exactly which
argument list set, but not in the second; or, more generally: which calls are made and in what order is unspecified.
appear in an odd number of sets. @code{lset-xor!} is allowed, but
not required to modify its first argument. @var{=} is used for testing @example
element equality. (lset-difference eqv? '(x y)) @result{} (x y)
(lset-difference eqv? '(1 2 3) '(3 1)) @result{} (2)
(lset-difference eqv? '(1 2 3) '(3) '(2)) @result{} (1)
@end example
The return from @code{lset-difference} may share a tail with
@var{list1}. @code{lset-difference!} may modify @var{list1} to form
its result.
@end deffn @end deffn
@deffn {Scheme Procedure} lset-diff+intersection = list1 list2 @dots{} @deffn {Scheme Procedure} lset-diff+intersection = list1 list2 @dots{}
@deffnx {Scheme Procedure} lset-diff+intersection! = list1 list2 @dots{} @deffnx {Scheme Procedure} lset-diff+intersection! = list1 list2 @dots{}
Return two values, the difference and the intersection of the argument Return two values (@pxref{Multiple Values}), the difference and
list sets. This works like a combination of @code{lset-difference} and intersection of the argument lists as per @code{lset-difference} and
@code{lset-intersection}, but is more efficient. @code{lset-intersection} above.
@code{lset-diff+intersection!} is allowed, but not required to modify
its first argument. @var{=} is used for testing element equality. You For two list arguments this partitions @var{list1} into those elements
have to use some means to deal with the multiple values these of @var{list1} which are in @var{list2} and not in @var{list2}. (But
procedures return (@pxref{Multiple Values}). for more than two arguments there can be elements of @var{list1} which
are neither part of the difference nor the intersection.)
One of the return values from @code{lset-diff+intersection} may share
a tail with @var{list1}. @code{lset-diff+intersection!} may modify
@var{list1} to form its results.
@end deffn
@deffn {Scheme Procedure} lset-xor = list1 list2 @dots{}
@deffnx {Scheme Procedure} lset-xor! = list1 list2 @dots{}
Return an XOR of the argument lists. For two lists this means those
elements which are in exactly one of the lists. For more than two
lists it means those elements which appear in an odd number of the
lists.
To be precise, the XOR of two lists @var{x} and @var{y} is formed by
taking those elements of @var{x} not equal to any element of @var{y},
plus those elements of @var{y} not equal to any element of @var{x}.
Equality is determined with the given @var{=} procedure, called as
@code{(@var{=} e1 e2)}. One argument is from @var{x} and the other
from @var{y}, but which way around is unspecified. Exactly which
calls are made is also unspecified, as is the order of the elements in
the result.
@example
(lset-xor eqv? '(x y)) @result{} (x y)
(lset-xor eqv? '(1 2 3) '(4 3 2)) @result{} (4 1)
@end example
The return from @code{lset-xor} may share a tail with one of the list
arguments. @code{lset-xor!} may modify @var{list1} to form its
result.
@end deffn @end deffn