lisp-一些结构

本文深入探讨Lisp中的数组创建、初始化、访问与修改,包括一维与多维数组的处理方式。同时,介绍了向量、字符串的操作,以及通用序列函数如remove、length、subseq等的使用。此外,还讲解了结构体、hash表的创建与操作方法。

数组

创建

(make-array 3); (NIL NIL NIL)
(make-array '(2 3)); ((NIL NIL NIL) (NIL NIL NIL))

一维数组直接传入数值,多位数组传入列表

初始

(make-array '(2 3) :initial-element 1); ((1 1 1) (1 1 1))
(make-array '(2 3) :initial-element (1)); (((1) (1) (1)) ((1) (1) (1)))

可以指定初始化值,默认为NIL,可以指定为任意指。

访问

(setf arr (make-array 3 :initial-element 1));
(aref arr 1); 1
(setf arr (make-array '(2 3) :initial-element 2))
(aref arr 1 1); 1

和其他的语言不一样,不存在数组嵌套数组构成多维数组的情况。

也就是说,(aref arr 0),当arr为多维数组的时候,是失败而不是返回一个数组。

设置

(setf arr (make-array 3)); (NIL NIL NIL)
(setf (aref arr 1) 9); (NIL 9 NIL)
(aref arr 1); 9

lisp的非基本数值,都是指针,所以(aref arr 1)可以取值,同样可以进行赋值,主要依赖指针进行操作。

向量

一维数组,可以当作向量,使用特殊的方法操作更快。

  • 创建
(setf arr (vector 'a 'b 'c)); (A B C)

可以把vectorlist进行对比,很快就能理解。

  • 查看
(aref arr 1); A
(svref arr 1); A

使用aref也能查看,但是针对的svref查询更快。

二分查找

(defun binary-search (arr start end target) (
    let ((len (length arr)))
        ; 如果长度为0
        ; 或者全部不匹配
        (if (or (zerop len) (eql start end))
            ; 返回NIL
            nil
            ; 如果等于开头
            (if (eql target (svref arr start))
                ; 返回开始索引
                start
                ; 如果等于结尾
                (if (eql target (svref arr end))
                    ; 返回末尾索引
                    end
                    ; 计算中心值
                    (let ((mid (/ (+ start end) 2)))
                        ; 取得中心值
                        (let ((value (svref arr mid)))
                            ; 如果大于
                            (if (> target mid)
                            		; (mid, end)
                                (binary-search arr mid end target)
                                ; (start, end)
                                (binary-search arr start mid target)
                            )
                            ; 中心变端点,就不重复比对了,想缩减压栈,可再比对一遍
                        )
                    )
                )
            )
        )
    )
)
(setf arr (vector 1 2 3 4 5 6 7 8 9))
(binary-search arr 0 8 5); 4
(svref arr 4); 5

字符串

声明

(setf str "mlpokijnbhuygvcftrdxzseawq")

 注意:是双引号

查看

(aref str 0); m
(char str 2); p

像一维数组那样访问也行,推荐char

修改

(setf (aref str 0) #\M); "M...."
(setf (char str 0) #'m); m...

配合访问指针进行操作

#/标示字符

排序

(sort str #'char<); (a...z)

改动的依然是本体数据,需要注意

连接

(concatenate 'string "head" " body " "tail"); "head body tail"

连接多个字符串

'string, 特殊名称

比较

(equal "abc" "abc"); T
(equal "abc" "ABC"); NIL
(string-equal "abc" "ABC"); T
  • 直接比较:equal
  • 忽略大小写:steing-equal

序列

  • 列表
  • 向量
  • 字符串

以上都是序列,如下函数都普遍使用于序列

functiondescription
remove移除
length长度
subseq截取
reverse反转
sort排序
every全部
some一些

查看

(elt '(a b c) 1); B

elt是序列通用的查看方法:

  • 数组:aref, svref
  • 列表:nth

具体参数如下

paramdescription
:key元素变化
:from-end反向查找
:test条件检测
:start起始位置
:end结束位置

如果想通过元素查找,而非索引的话

(position #\b "abc"); 1
(position-if #'(lambda (x) (equal x #\b)) "abc")

类似的还有这几种,但是参数不一定都支持

  • member
    • member-if
  • find
    • find-if

reduce

(reduce #'+ '(1 2 3 4 5 6 7 8 9))

作用不多说,打架都知道

去重

(remove-duplicates '( 1 2 1 1 1 4 4 2 3));(1 4 2 3)

只保留最后一个值,所以去重来

输出

(setf result (format nil "~A" 'fuck))

原来的format中传入的是t,当传入nil,不会打印,但是会把打印值直接返回

结构

定义

(defstruct person name age gender)

第一个参数为结构体名称,后续都是该结构的属性字段

方法

定义结构之后,会自动生成各种方法

  • 构造
(make-person); #S(PERSON :NAME NIL :AGE NIL :GENDER NIL)

属性默认都是NIL,但是可以自己传入指定的值

(make-person :name 'godme :age 99 :gender 'male)
; #S(PERSON :NAME GODME :AGE 99 :GENDER MALE)

没有设置的保留默认NIL

  • 属性指针
(person-name p); svref的访问,查询和设置两用
  • 类型校验
(person-p p); 类型检查

查询

(setf p (make-person :name 'godme :age 99 :gender 'male))
(person-name p); GODME

设置

(setf (person-name p) 'judas); 
(person-name p); JUDAS

类型

(person-p p); T
(type-p p 'person); T

hash

创建

(make-hash-table); 
(make-hash-table :size 5); 可指定初始化长度
(setf colors (make-hash-table)); 

查询

(gethash 'r colors); NIL;NIL
  • 第一个:存储的值,找不到时候返回NIL
  • 第二个:是否存储,当T表示存储的时候,NIL才是存储的值,否则仅仅是默认返回的NIL

设置

(setf (gethash 'r colors) 'red); 
(gethash 'r colors); RED; T
(setf (gethash 'b colors) '(black dark))
(gethash 'b colors); (BLACK DARK)
  • 还是查询索引指针进行赋值
  • 支持各种元素

移除

(remhash 'b colors); (R.RED)

比较

(setf (gethash '(1 2 3) colors) '(4 5 6));键值还可以是对象
(gethash '(1 2 3) colors); NIL; NIL; 但是取出来就有问题

因为默认的比较方法是eql,也就是说,只有是同一个对象,是同一个地址,才能取出来。

不过,创建hash的时候,我们也能够自己指定比对方法。

(setf h (make-hash-table :test #'equal))
(setf (gethash '(1 2 3) h) '(4 5 6))
(gethash '(1 2 3)); (4 5 6)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值