LISP - 列表


列表是传统 LISP 中最重要和主要的复合数据结构。目前的 Common LISP 提供了其他数据结构,例如向量、哈希表、类或结构。

列表是单链表。在 LISP 中,列表被构造为一个名为cons的简单记录结构链接在一起的链。

缺点记录结构

cons是一个记录结构,包含两个组件,称为carcdr

Cons 单元格或 cons 是对象,是使用函数cons 创建的值对。

cons函数接受两个参数并返回一个包含这两个值的新 cons 单元格。这些值可以是对任何类型对象的引用。

如果第二个值不是 nil 或另一个 cons 单元格,则这些值将打印为用括号括起来的点对。

cons 单元格中的两个值称为carcdr。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 结构来创建单个链表,例如,列表 (ABC) 由通过其 cdrs 链接在一起的三个 cons 单元组成

从图表上看,它可以表示为 -

LISP 中的列表

尽管 cons 单元格可用于创建列表,但是,通过嵌套cons函数调用构造列表并不是最佳解决方案。list函数更适合在 LISP 中创建列表。

列表函数可以接受任意数量的参数,并且由于它是一个函数,因此它会计算其参数。

一个其余函数给出列表的第一个元素和其余部分。以下示例演示了这些概念。

实施例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))

实施例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

它接受一个列表作为参数,并返回其第一个元素。

2

cdr

它接受一个列表作为参数,并返回一个没有第一个元素的列表

3

缺点

它接受两个参数,一个元素和一个列表,并返回一个列表,其中元素插入到第一个位置。

4

列表

它接受任意数量的参数并返回一个列表,其中参数作为列表的成员元素。

5

附加

它将两个或多个列表合并为一个。

6

最后的

它接受一个列表并返回一个包含最后一个元素的列表。

7

成员

它接受两个参数,如果第一个参数是第二个参数的成员,则第二个参数必须是列表,然后返回从第一个参数开始的列表的其余部分。

8

撤销

它接受一个列表并返回一个列表,其中顶部元素的顺序相反。

请注意,所有序列函数都适用于列表。

实施例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 (cd) (efg))) 将返回 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)