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中某个元素。

一些其他的功能函数:

NameRequired ArgumentsReturns
COUNTItem and sequenceItem在序列中出现的次数
FINDItem and sequenceItem或NIL
POSITIONItem and sequenceItem的索引或NIL
REMOVEItem and sequence移除了所有item的序列
SUBSTITUTENew 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逆序操作SequenceNIL
: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。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值