LISP - 列表
列表是传统 LISP 中最重要和主要的复合数据结构。 目前的 Common LISP 提供了其他数据结构,例如向量、哈希表、类或结构。
列表是单链表。 在 LISP 中,列表被构造为链接在一起的名为 cons 的简单记录结构链。
cons 记录结构
cons 是一个记录结构,包含两个组件,称为car 和cdr。
Cons 单元格或 cons 是对象,是使用函数 cons 创建的值对。
cons 函数接受两个参数并返回一个包含这两个值的新 cons 单元格。 这些值可以是对任何类型对象的引用。
如果第二个值不是 nil 或另一个 cons 单元格,则这些值将打印为用括号括起来的点对。
cons 单元格中的两个值称为 car 和 cdr。car 函数用于访问第一个值,cdr 函数用于访问第二个值。
示例
创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。
(write (cons 1 2)) (terpri) (write (cons 'a 'b)) (terpri) (write (cons 1 nil)) (terpri) (write (cons 1 (cons 2 nil))) (terpri) (write (cons 1 (cons 2 (cons 3 nil)))) (terpri) (write (cons 'a (cons 'b (cons 'c nil)))) (terpri) (write ( car (cons 'a (cons 'b (cons 'c nil))))) (terpri) (write ( cdr (cons 'a (cons 'b (cons 'c nil)))))
执行代码时,会返回以下结果 −
(1 . 2) (A . B) (1) (1 2) (1 2 3) (A B C) A (B C)
上面的示例显示了如何使用 cons 结构来创建单个链接列表,例如,列表 (A B C) 由通过其 cdrs 连接在一起的三个 cons 单元组成。
从图表上看,它可以表示为 −
LISP 中的列表
尽管 cons 单元格可用于创建列表,但是,通过嵌套 cons 函数调用构造列表并不是最佳解决方案。 list 函数更适合在 LISP 中创建列表。
列表函数可以接受任意数量的参数,并且由于它是一个函数,因此它会计算其参数。
first 和 rest 函数给出列表的第一个元素和其余部分。 以下示例演示了这些概念。
示例 1
创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。
(write (list 1 2)) (terpri) (write (list 'a 'b)) (terpri) (write (list 1 nil)) (terpri) (write (list 1 2 3)) (terpri) (write (list 'a 'b 'c)) (terpri) (write (list 3 4 'a (car '(b . c)) (* 4 -2))) (terpri) (write (list (list 'a 'b) (list 'c 'd 'e)))
执行代码时,会返回以下结果 −
(1 2) (A B) (1 NIL) (1 2 3) (A B C) (3 4 A B -8) ((A B) (C D E))
Example 2
创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。
(defun my-library (title author rating availability) (list :title title :author author :rating rating :availabilty availability) ) (write (getf (my-library "Hunger Game" "Collins" 9 t) :title))
执行代码时,会返回以下结果 −
"Hunger Game"
列表操作函数
下表提供了一些常用的列表操作函数。
序号 | 函数及说明 |
---|---|
1 | car 它接受一个列表作为参数,并返回其第一个元素。 |
2 | cdr 它接受一个列表作为参数,并返回一个没有第一个元素的列表 |
3 | cons 它需要两个参数,一个元素和一个列表,并返回一个列表,该元素插入到第一个位置。 |
4 | list 它接受任意数量的参数并返回一个列表,其中参数作为列表的成员元素。 |
5 | append 它将两个或多个列表合并为一个。 |
6 | last 它接受一个列表并返回一个包含最后一个元素的列表。 |
7 | member 它接受两个参数,如果第一个参数是第二个参数的成员,则第二个参数必须是列表,然后返回从第一个参数开始的列表的其余部分。 |
8 | reverse 它接受一个列表并返回一个列表,其中顶部元素的顺序相反。 |
请注意,所有序列函数都适用于列表。
示例 3
创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。
(write (car '(a b c d e f))) (terpri) (write (cdr '(a b c d e f))) (terpri) (write (cons 'a '(b c))) (terpri) (write (list 'a '(b c) '(e f))) (terpri) (write (append '(b c) '(e f) '(p q) '() '(g))) (terpri) (write (last '(a b c d (e f)))) (terpri) (write (reverse '(a b c d (e f))))
执行代码时,会返回以下结果 −
A (B C D E F) (A B C) (A (B C) (E F)) (B C E F P Q G) ((E F)) ((E F) D C B A)
car 和 cdr 函数的串联
car 和 cdr 函数及其组合允许提取列表的任何特定元素/成员。
但是,car 和 cdr 函数的序列可以通过在字母 c 和 r 内连接 car 的字母 a 和 cdr 的 d 来缩写。
例如,我们可以编写 cadadr 来缩写函数调用顺序 - car cdr car cdr。
因此,(cadadr '(a (c d) (e f g))) 将返回 d
示例 4
创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。
(write (cadadr '(a (c d) (e f g)))) (terpri) (write (caar (list (list 'a 'b) 'c))) (terpri) (write (cadr (list (list 1 2) (list 3 4)))) (terpri)
执行代码时,会返回以下结果 −
D A (3 4)