LISP - 序列


序列是 LISP 中的一种抽象数据类型。向量和列表是该数据类型的两个具体子类型。在序列数据类型上定义的所有功能实际上都应用于所有向量和列表类型。

在本节中,我们将讨论序列上最常用的函数。

在开始操作序列(即向量和列表)的各种方法之前,让我们看一下所有可用函数的列表。

创建序列

函数 make-sequence 允许您创建任何类型的序列。该函数的语法是 -

make-sequence sqtype sqsize &key :initial-element

它创建一个类型为sqtype且长度为sqsize的序列

您可以选择使用:initial-element参数指定某个值,然后每个元素都将初始化为该值。

例如,创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(write (make-sequence '(vector float) 
   10 
   :initial-element 1.0))

当您执行代码时,它会返回以下结果 -

#(1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)

序列上的通用函数

先生。 功能说明
1

埃尔特

它允许通过整数索引访问各个元素。

2

长度

它返回序列的长度。

3

子序列

它通过提取从特定索引开始并继续到特定结束索引或序列末尾的子序列来返回子序列。

4

复制序列

它返回一个序列,其中包含与其参数相同的元素。

5

充满

它用于将序列的多个元素设置为单个值。

6

代替

它需要两个序列,并且通过将第二个参数序列中的连续元素复制到第一个参数序列中,对第一个参数序列进行破坏性修改。

7

数数

它接受一个项目和一个序列,并返回该项目在序列中出现的次数。

8

撤销

它返回一个包含与参数相同的元素但顺序相反的序列。

9

反向

它返回包含与序列相同的元素但顺序相反的相同序列。

10

连接

它创建一个包含任意数量序列串联的新序列。

11

位置

它接受一个项目和一个序列,并返回该项目在序列中的索引或 nil。

12

寻找

它需要一个项目和一个序列。它找到序列中的项目并返回它,如果没有找到则返回 nil。

13

种类

它接受一个序列和一个双参数谓词,并返回序列的排序版本。

14

合并

它接受两个序列和一个谓词,并根据谓词返回通过合并两个序列而产生的序列。

15

地图

它接受一个 n 参数函数和 n 个序列,并返回一个新序列,其中包含将该函数应用于序列的后续元素的结果。

16

一些

它将谓词作为参数并迭代参数序列,并返回谓词返回的第一个非 NIL 值,或者如果从未满足谓词则返回 false。

17 号

每一个

它采用谓词作为参数并迭代参数序列,一旦谓词失败,它就会终止并返回 false。如果谓词始终满足,则返回 true。

18

没有

它将谓词作为参数并迭代参数序列,一旦满足谓词就返回 false,如果不满足则返回 true。

19

非常注意

它将谓词作为参数并迭代参数序列,一旦谓词失败就返回 true,如果谓词始终满足则返回 false。

20

减少

它映射单个序列,首先将双参数函数应用于序列的前两个元素,然后应用于函数返回的值和序列的后续元素。

21

搜索

它搜索序列以找到满足某些测试的一个或多个元素。

22

消除

它接受一个项目和一个序列,并返回删除了项目实例的序列。

23

删除

这也接受一个项目和一个序列,并返回一个与参数序列相同类型的序列,该序列具有除该项目之外的相同元素。

24

代替

它接受一个新项目、一个现有项目和一个序列,并返回一个序列,其中现有项目的实例替换为新项目。

25

n替代

它接受一个新项目、一个现有项目和一个序列,并返回相同的序列,其中现有项目的实例替换为新项目。

26

不匹配

它需要两个序列并返回第一对不匹配元素的索引。

标准序列函数关键字参数

争论 意义 默认值
:测试 它是一个双参数函数,用于将项目(或 :key 函数提取的值)与元素进行比较。 EQL
:钥匙 从实际序列元素中提取键值的单参数函数。NIL 表示按原样使用元素。
:开始 子序列的起始索引(包括)。 0
:结尾 子序列的结束索引(不包括)。NIL 表示序列结束。
:从末端开始 如果为 true,则序列将以相反的顺序从结束到开始遍历。
:数数 数字表示要删除或替换的元素数量,或 NIL 表示所有元素(仅限 REMOVE 和 SUBSTITUTE)。

我们刚刚讨论了各种函数和在这些处理序列的函数中用作参数的关键字。在接下来的部分中,我们将通过示例了解如何使用这些函数。

求长度和元素

length函数返回序列的长度,elt函数允许您使用整数索引访问各个元素

例子

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(setq x (vector 'a 'b 'c 'd 'e))
(write (length x))
(terpri)
(write (elt x 3))

当您执行代码时,它会返回以下结果 -

5
D

修改序列

某些序列函数允许迭代序列并执行一些操作,例如搜索、删除、计数或过滤特定元素,而无需编写显式循环。

以下示例演示了这一点 -

实施例1

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(write (count 7 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (remove 5 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (delete 5 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (substitute 10 7 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (find 7 '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (position 5 '(1 5 6 7 8 9 2 7 3 4 5)))

当您执行代码时,它会返回以下结果 -

2
(1 6 7 8 9 2 7 3 4)
(1 6 7 8 9 2 7 3 4)
(1 5 6 10 8 9 2 10 3 4 5)
7
1

实施例2

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(write (delete-if #'oddp '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (delete-if #'evenp '(1 5 6 7 8 9 2 7 3 4 5)))
(terpri)
(write (remove-if #'evenp '(1 5 6 7 8 9 2 7 3 4 5) :count 1 :from-end t))
(terpri)
(setq x (vector 'a 'b 'c 'd 'e 'f 'g))
(fill x 'p :start 1 :end 4)
(write x)

当您执行代码时,它会返回以下结果 -

(6 8 2 4)
(1 5 7 9 7 3 5)
(1 5 6 7 8 9 2 7 3 5)
#(A P P P E F G)

排序和合并序列

排序函数采用一个序列和一个双参数谓词,并返回序列的排序版本。

实施例1

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(write (sort '(2 4 7 3 9 1 5 4 6 3 8) #'<))
(terpri)
(write (sort '(2 4 7 3 9 1 5 4 6 3 8) #'>))
(terpri)

当您执行代码时,它会返回以下结果 -

(1 2 3 3 4 4 5 6 7 8 9)
(9 8 7 6 5 4 4 3 3 2 1)

实施例2

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(write (merge 'vector #(1 3 5) #(2 4 6) #'<))
(terpri)
(write (merge 'list #(1 3 5) #(2 4 6) #'<))
(terpri)

当您执行代码时,它会返回以下结果 -

#(1 2 3 4 5 6)
(1 2 3 4 5 6)

序列谓词

函数 every、some、notany 和 notever 称为序列谓词​​。

这些函数迭代序列并测试布尔谓词。

所有这些函数都将谓词作为第一个参数,其余参数是序列。

例子

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(write (every #'evenp #(2 4 6 8 10)))
(terpri)
(write (some #'evenp #(2 4 6 8 10 13 14)))
(terpri)
(write (every #'evenp #(2 4 6 8 10 13 14)))
(terpri)
(write (notany #'evenp #(2 4 6 8 10)))
(terpri)
(write (notevery #'evenp #(2 4 6 8 10 13 14)))
(terpri)

当您执行代码时,它会返回以下结果 -

T
T
NIL
NIL
T

映射序列

我们已经讨论过映射函数。类似地,映射函数允许您将函数应用于一个或多个序列的后续元素。

map函数采用 n 个参数函数和 n 个序列,并在将该函数应用于序列的后续元素后返回一个新序列

例子

创建一个名为 main.lisp 的新源代码文件,并在其中键入以下代码。

(write (map 'vector #'* #(2 3 4 5) #(3 5 4 8)))

当您执行代码时,它会返回以下结果 -

#(6 15 16 40)