Vectors是Common Lisp中基于整数索引的基础容器。它们分两类:一类是固定大小的vector,一类是可变大小的vector。可使用函数VECTOR定义固定大小的Vector:
(vector) -> #()
(vector 1) -> #(1)
(vector 1 2) -> #(1 2)
应该使用VECTOR或更加通用的MAKE-ARRAY来创建可能被修改的vectors。
MAKE-ARRAY既可以创建固定大小的vector,也可以创建可变大小的vector。MAKE-ARRAY的一个必须参数是数组的维度。因为vector是一维数组,所以只需包含vector的大小。当没有其他的参数设定时,MAKE-ARRAY将创建一个拥有未初始化元素的vector,在它们被访问前,必须先被设定。如果需要在创建vector时,其元素已被设定了初始值,可以指定:initial-element参数来完成。
(make-array 5 :initial-element nil) -> #(NIL NIL NIL NIL NIL)
上面的代码,创建了一个包含5个初始化为NIL的元素的vector。
当MAKE-ARRAY用于创建可变大小的vector时,将会跟踪实际存入vector中的元素个数,而这个个数就保存在vector的fill pointer(下一个元素将要填充的位置索引)中。在通过MAKE-ARRAY创建vector时,可以通过:fill-pointer来指定vector的初始填充位置。
(make-array 5 :fill-pointer 0) -> #()
上述代码定义了一个大小为5的vector,但是由于其fill-pointer为0,所以它看起来如同一个空的vector。
VECTOR-PUSH用于将一个元素添加大一个可变vector的末尾,并返回该元素的索引,同时增加fill pointer的值;
VECTOR-POP将返回最近被push的元素,并减小fill pointer的值。
(defparameter *vec* (make-array 2 :fill-pointer 0))
(vector-push 1 *vec*) -> *vec*为#(1),返回0
(vector-push 2 *vec*) -> *vec*为#(1 2),返回1
(vector-push 3 *vec*) -> *vec*为#(1 2),返回NIL
如果想要创建一个完全可resizable的vector,则在通过MAKE-ARRAY创建vector时,需要指定其:adjustable参数的值。
(make-array 5 :fill-pointer 0 :adjustable t) -> #()
当要需要向adjustable vector添加元素并自动扩展vector大小时,可通过VECTOR-PUSH-EXTEND进行。
如果需要指定vector中元素的具体类型,可在MAKE-ARRAY创建vector时,指定其参数:element-type,该参数可取值为CHARACTER,BIT等:
(make-array 5 :fill-pointer 0 :adjustable t :element-type 'character) -> ""
如果要得到一个vector的长度,可以使用函数LENGTH,如果要访问vector中的某一个元素,可以使用函数ELT(vector的索引起始值为0)。
(defparameter *vec* (vector 1 2))
(length *vec*) -> 2
(elt *vec* 0) -> 1
(elt *vec* 1) -> 2
(elt *vec* 2) -> error
可以通过setf更改vector中某个元素。
一些其他的功能函数:
Name | Required Arguments | Returns |
COUNT | Item and sequence | Item在序列中出现的次数 |
FIND | Item and sequence | Item或NIL |
POSITION | Item and sequence | Item的索引或NIL |
REMOVE | Item and sequence | 移除了所有item的序列 |
SUBSTITUTE | New item, item, and sequence | 所有的指定Item被替换为新的Item的序列 |
(count 1 #(1 2 1 2 3)) -> 2
(remove 1 '(1 2 1 2 3)) -> (2 2 3)
(substitute 10 1 '(1 2 1 2 3)) -> (10 2 10 2 3)
(find 2 '(1 2 1 2 3)) -> 2
(position 3 '(1 2 1 2 3)) -> 4
值得注意的是REMOVE和SUBSTITUE返回的序列(sequence)和其参数的序列的类型是相同的。
上述函数的Keyword Arguments如下表所示:
Argument |
Meaning |
Default |
:test | 设定一个两参数的比较函数,用于特定目的的比较操作(类似于C++ STL中的functor) | EQL |
:key | 传入一个单参数函数,用于提取每个元素的key value,该值将被用于和参数中指定的Item值做比较 | NIL |
:start | 对Sequence操作的起始位置 | 0 |
:end | 对Sequence操作的终止位置 | NIL |
:from-end | 逆序操作Sequence | NIL |
:count | 指定REMOVE或SUBSTITUTE移除或替换元素的个数 | NIL |
(count "foo" #("Foo" "bar")) -> 0
(count "foo" #("Foo" "bar") :test #'string-equal) -> 1
(find 'a #((a 10) (b 20) (a 30))) -> NIL
(find 'a #((a 10) (b 20) (a 30)) :key #'first) -> (A 10)
(find 'a #((a 10) (b 20) (a 30)) :key #'first :from-end t) -> (A 30)
(remove #\a "a1a2a3a4" :count 2) -> "12a3a4"
函数COPY-SEQ用于创建一个新的sequence,新的sequence内容拷贝至作为其输入参数的sequence;
函数REVERSE用于创建一个sequence的逆序sequence。
函数CONCATENATE用于创建一个新的sequence,它的元素包含了作为其参数的所有sequence中的元素,在使用时,必须指定sequence的类型。
(concatenate 'vector #(1 2 3) '(4 5 6)) -> #(1 2 3 4 5 6)
(concatenate 'list #(1 2 3) '(4 5 6)) -> (1 2 3 4 5 6)
(concatenate 'string "abc" '(#\d #\e #\f)) -> "abcdef"
函数SORT(不稳定)和STABLE-SORT(稳定)用于排序一个sequence:
(sort (vector "foo" "bar") #'string<) -> #("bar" "foo")
函数MERGE用于按照指定predicate来合并两个sequence:
(merge 'vector #(1 3 5) #(2 4 6) #'<) -> #(1 2 3 4 5 6)
函数SUBSEQ用于获取一个sequence的子sequence:
(subseq "foobarbaz" 3) -> "barbaz"
(subseq "foobarbaz" 3 6) -> "bar"
(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"
函数MAKE-HASH-TABLE用于创建一个hash表。
可以通过:test设定比较运算,默认的情况为EQL,其他可选值为EQUAL、EQ和EQUALP。
(defparameter *h* (make-hash-table))
(gethash 'foo *h*) -> NIL
(setf (gethash 'foo *h*) 'quux)
(gethash 'foo *h*) -> QUUX
(remhash 'foo *h*) -> NIL
对hash table操作的函数有GETHASH、REMHASH和CLRHASH。