Common Lisp的标准容器

Vectors

Vectors是Common Lisp中基于整数索引的基础容器。它们分两类:一类是固定大小的vector,一类是可变大小的vector。可使用函数VECTOR定义固定大小的Vector:

(vector)       -> #()
(vector 1)     -> #(1)
(vector 1 2)   -> #(1 2)

#(...)用于保存将要被PRINTing或READing的vectors,但是通过该语法定义的vector,其元素不能够被修改。

应该使用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"


Hash Table

函数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。


你可能感兴趣的:(Common,Lisp)