Subsequence Manipulations
Another set of functions allows you to manipulate subsequences of existing sequences. The most basic of these is **SUBSEQ**
, which extracts a subsequence starting at a particular index and continuing to a particular ending index or the end of the sequence. For instance:
(subseq "foobarbaz" 3) ==> "barbaz"
(subseq "foobarbaz" 3 6) ==> "bar"
**SUBSEQ**
is also **SETF**
able, but it won’t extend or shrink a sequence; if the new value and the subsequence to be replaced are different lengths, the shorter of the two determines how many characters are actually changed.
(defparameter *x* (copy-seq "foobarbaz"))
(setf (subseq *x* 3 6) "xxx") ; subsequence and new value are same length
*x* ==> "fooxxxbaz"
(setf (subseq *x* 3 6) "abcd") ; new value too long, extra character ignored.
*x* ==> "fooabcbaz"
(setf (subseq *x* 3 6) "xx") ; new value too short, only two characters changed
*x* ==> "fooxxcbaz"
You can use the **FILL**
function to set multiple elements of a sequence to a single value. The required arguments are a sequence and the value with which to fill it. By default every element of the sequence is set to the value; :start
and :end
keyword arguments can limit the effects to a given subsequence.
If you need to find a subsequence within a sequence, the **SEARCH**
function works like **POSITION**
except the first argument is a sequence rather than a single item.
(position #\b "foobarbaz") ==> 3
(search "bar" "foobarbaz") ==> 3
On the other hand, to find where two sequences with a common prefix first diverge, you can use the **MISMATCH**
function. It takes two sequences and returns the index of the first pair of mismatched elements.
(mismatch "foobarbaz" "foom") ==> 3
It returns **NIL**
if the strings match. **MISMATCH**
also takes many of the standard keyword arguments: a :key
argument for specifying a function to use to extract the values to be compared; a :test
argument to specify the comparison function; and :start1
, :end1
, :start2
, and :end2
arguments to specify subsequences within the two sequences. And a :from-end
argument of **T**
specifies the sequences should be searched in reverse order, causing **MISMATCH**
to return the index, in the first sequence, where whatever common suffix the two sequences share begins.
(mismatch "foobar" "bar" :from-end t) ==> 3