向量类型

; 向量(也可以叫一维数组) 哈希表
; 向量 整数索引 定长向量(连续内存区域)和变长向量
; 函数VECTOR接受任意参数,生成定长向量
(vector) #()
(vector 1) #(1)
(vector 1 2) #(1 2)
; 使用vector或者make-array来创建打算修改的向量
; make-array应用很广泛,多维变长都行
; 一个必要参数是数组长度,被访问前设置其值
(make-array 5 :initial-element nil) ;#(nil nil nil nil nil)
; 创建变长向量,得需要填充指针
(make-array 5 :fill-pointer 0) ;#()
; (vector-push ) ;填充指针+1,返回位置
; (vector-pop) ;填充指针-1,返回元素
; 当前也不是变长的,最多5个元素,如果需要变长则:adjustable t
(defparameter *x* (make-array 5 :fill-pointer 0))
(vector-push 'b *x*)
(vector-push 'a *x*)
(vector-pop *x*)
 
; 向量的子类型,特化向量只保存某一类型的,访问快存储紧凑
; 字符串就是一种特化向量
; 初始值为空的变长字符串
(defparameter *y* (make-array 5 :fill-pointer 0 
                                :adjustable t
                                :element-type 'character))
; 位向量 都是01按位操作 #*01010110111 :element-type BIT
; 作为序列的向量之函数
(defparameter *x* (vector 1 2 3))
(length *x*) ;3
(elt *x* 0)
(elt *x* 1)
(elt *x* 2)
; (elt *x* 3) error
; elt也是支持setf的位置
(setf (elt *x* 2) 33)
; ;;;;序列迭代函数,对所有序列管用
; (count 项 序列) 出现次数
; (find 项 序列) 项或者nil
; (position 项 序列)索引或者nil
; (remove 项 序列) 移出后的序列,类型和原序列相同
; (substitute 新项 项 序列)替换后的序列,类型和原数列相同
(count 3 #(3 4 5 3 6 9)) ;2
(find 3 #(3 4 5)) ;3
(position #\a "lambda");1
(remove #\a "lambda") ;lmbd
(substitute 33 3 #(3 4 5)) ;(33 4 5)
; 改变以上函数的行为:test :key
; 比较参数(接收一个函数,默认值是EQL):test 接收两个参数,返回布尔值的函数
; :key是一个接收单参数的函数,用于在序列的每个元素上抽取关键值替代元素自身进行匹配
(count "foo" ("foo" "bar" "test") :test #'string=)
(find 'c #((a 10) (b 20) (c 30)) :key #'first)
(find 20 #((a 10) (b 20) (c 30)) :key #'second)
 
; 将函数的效果限定在特定子序列上可以用 :from :end (索引位置)左闭右开区间>=from < end
; 倒序参数:from-end 非nil时起作用
; 限制要移出或者替换的个数:count,默认值nil全部
; 高阶函数变体,以上五个函数加上-IF -IF-NOT
; -IF计数查找移出替换序列中函数参数返回为真的元素
; -IF-NOT计数查找移出替换序列中函数参数不返回真的元素
(count-if #'evenp #(1 2 3 4 5)) ;2
(count-if-not #'evenp #(1 2 3 4 5)) ;3
(position-if #'digit-char-p "abcd0001") ;4
(remove-if-not #'(lambda (x) (char= (elt x 0) #\f)) #("f0" "fun" "bar" "boot"))
#'alpha-char-p
(remove-if-not #'alpha-char-p "a234bc")
(remove-duplicates #(1 2 3 4 5 3 4)) ;#(1 2 3 4 5)
 
; 整个序列上的操作
; copy-seq返回一个相同的序列
; reverse返回一个逆序的序列
; 这两个函数都不会复制元素本身,只有返回的序列是一个新对象??????
; concatenate 将任意序列返回指定的类型 VECTOR LIST STRING
(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" '(#\4 #\5 #\6)) ;"abc456"
 
; 排序与合并
; sort
; stable-sort 不会重排被谓词视为等价的元素
; 接受一个序列和一个两实参的谓词 返回总重排序的序列
(sort #("foo" "bar" "baz") #'string<)
; 这两个函数是破坏性函数,会或多或少修改它的参数
; 1总是对其返回值做一些事情,赋给一个变量或者传给一个函数
; (setf my-sequence (sort my-sequence #'<))
; 2除非不在需要传递给破坏性函数的对象,否则传给它一个副本
; 可以接收:key用于抽取元素进行比较
 
; merge合并
(merge 'list '(1 2) '(3 4 1) #'<) ;(1 2 3 4 1)
; 如果传递给merge的序列有序,则结果有序
; 子序列操作
; (subseq 序列 开始索引 终止索引)
; 支持setf
(defparameter *x* (copy-seq "abcdefg"))
(setf (subseq *x* 3 5) "qqqqq");abcqqfg
; 两者之中较短的一个决定多少被替换
; fill函数,填充(fill *x* #\a :start 1 :end 3)省略关键字则全部填充
; search函数 可以查找子序列,方法同position函数
(position #\b "foobarbaz");3
(search "bar" "foobar");3
; 相同前缀的序列首次分叉的位置mismatch,匹配则返回nil
(mismatch "foobar" "foom");3
; 可以使用:key :test :from-end :start1 :end1 :start2 :end2关键字
; :from-end t 搜索相同后缀在第一个序列中索引位置
 
; 序列谓词 
; every['evri]每一个都满足 
; some某个或某些满足
; notany不是某个或某些满足(都不满足)
; notevery不是所有的都满足(有不满足的)
; 在序列上迭代测试一个布尔谓词(every #'evenp #(1 2 3 4 5)) nil
; every 谓词失败时返回假,否则真
; some返回谓词返回的第一个非nil值,否则nil
; notany在谓词满足时返回假,从未满足返回真
; notevery在谓词失败时返回真,谓词总是满足返回假
(every #'evenp #(1 2 3 4 5)) ;nil
(some #'evenp #(1 2 3 4 5)) ;t
(notany #'evenp #(1 2 3 4 5)) ;nil
(notevery #'evenp #(1 2 3 4 5)) ;t
(every #'> #(5 4) #(1 2));t
 
; 序列映射函数
; map接受一个n参数函数和n个序列,返回一个新序列
; 和merge concatenate 一样需要指定返回类型
(map 'vector #'* #(1 2 3) #(4 5 6));#(4 10 18)
; map-into不产生新序列,而是放到其中一个里
; (map-into a #'+ a b c)
; map-into 以最短的序列为标准进行操作,不会自动扩展可调整向量的大小
 
; reduce
; 将序列提炼成一个单独的值,作用在单独的序列上
; 序列中的前2个元素放到2参数函数中计算,结果再和第三个元素计算……
(reduce #'+ #(1 2 3 4 5 6 7 8 9 10)) ;55
; (reduce #'max numbers)
; 关键字参数:key :from-end :start :end
; :initial-value放到第一个元素之前,如果:from-end t则放到最后一个元素之后
 
 
; 哈希表
; 可以用任意对象作为key
(MAKE-HASH-TABLE :test EQL)
; 键值默认比较是EQL,可以根据需要改成EQUAL EQUALP EQ
(defparameter *h* (make-hash-table))
(gethash 'foo *h*) ;nil
(setf (gethash 'foo *h*) 'quux)
(gethash 'foo *h*) ;quux
; gethash其实返回2个值,
; 一个是给定键下面的值(可能存储一个nil),
; 另一个是一个是否存在该键的布尔值
; 可以使用MULTIple-VALUE-BIND宏来处理多重返回值,类似于let的变量绑定
(defun show-value (key hash-table)
  (multiple-value-bind (value present) (gethash key hash-table)
    (if present
      (format nil "~a actually present" value)
      (format nil "~a key not found" value))))
(show-value 'foo *h*)
; 移除键值对
(remhash 'foo *h*)
; 清空哈希表
(clrhash *h*)
 
 
; 哈希表迭代
; maphash 接受一个两参数函数 和 哈希表 依次迭代哈希表的键值对
(map-hash #'(lambda (k v) (format t "key:~a value:~a~%" k v)) *h*)
; 迭代过程中添加或者移除键值对可能会产生后果
; 但可以用setf和gethash更改值,REMHASH移除当前项
(maphash #'(lambda (k v) (when (< v 10) (remhash k *h*))) *h*)
; loop宏
(loop fro k being the hash-keys in *h* using (hash-value v)
  do (format t "key:~a value:~a~%" k v))
 




转载于:https://www.cnblogs.com/aczhanghua/archive/2012/04/11/2441717.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值