Lisp - 序列



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

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

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

创建序列

函数 `make-sequence` 允许您创建任何类型的序列。此函数的语法为:

make-sequence sqtype sqsize &key :initial-element

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

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

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

main.lisp

; create a sequence of 10 floating numbers initilized with 1.0
(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

elt

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

2

length

它返回序列的长度。

3

subseq

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

4

copy-seq

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

5

fill

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

6

replace

它接受两个序列,第一个参数序列通过从第二个参数序列中复制连续元素到其中来被破坏性地修改。

7

count

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

8

reverse

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

9

nreverse

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

10

concatenate

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

11

position

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

12

find

它接受一个项目和一个序列。它在序列中查找项目并返回它,如果未找到则返回 nil。

13

sort

它接受一个序列和一个二元谓词,并返回序列的排序版本。

14

merge

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

15

map

它接受一个 n 元函数和 n 个序列,并在将函数应用于序列的后续元素后返回一个新序列。

16

some

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

17

every

它接受一个谓词作为参数,并迭代参数序列,一旦谓词失败,它就会终止并返回 false。如果谓词总是满足,则返回 true。

18

notany

它接受一个谓词作为参数,并迭代参数序列,一旦谓词满足则返回 false,如果从未满足则返回 true。

19

notevery

它接受一个谓词作为参数,并迭代参数序列,一旦谓词失败则返回 true,如果谓词总是满足则返回 false。

20

reduce

它在一个序列上进行映射,首先将一个二元函数应用于序列的前两个元素,然后应用于函数返回的值和序列的后续元素。

21

search

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

22

remove

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

23

delete

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

24

substitute

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

25

nsubstitute

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

26

mismatch

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

标准序列函数关键字参数

参数 含义 默认值
:test 它是一个二元函数,用于将项目(或由 :key 函数提取的值)与元素进行比较。 EQL
:key 从实际序列元素中提取键值的单参数函数。NIL 表示按原样使用元素。 NIL
:start 子序列的起始索引(包含)。 0
:end 子序列的结束索引(不包含)。NIL 表示序列的结尾。 NIL
:from-end 如果为真,则将从后向前反向遍历序列。 NIL
:count 指示要移除或替换的元素数量,或 NIL 表示全部(仅限 REMOVE 和 SUBSTITUTE)。 NIL

我们刚刚讨论了各种函数和关键字,这些函数和关键字用作这些函数在序列上工作时的参数。在接下来的章节中,我们将看到如何使用示例使用这些函数。

查找长度和元素

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

示例

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

main.lisp

; set x as a vector of 5 characters
(setq x (vector 'a 'b 'c 'd 'e))
; print length of x
(write (length x))
; terminate printing
(terpri)
; print value at index 3
(write (elt x 3))

输出

执行代码时,它将返回以下结果:

5
D

修改序列

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

以下示例演示了这一点:

示例

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

main.lisp

; print count of 7 in the list
(write (count 7 '(1 5 6 7 8 9 2 7 3 4 5)))
; terminate printing
(terpri)
; remove occurences of 5 from the list
(write (remove 5 '(1 5 6 7 8 9 2 7 3 4 5)))
; terminate printing
(terpri)
; delete occurences of 5 from the list
(write (delete 5 '(1 5 6 7 8 9 2 7 3 4 5)))
; terminate printing
(terpri)
; substitute 7 with 10 in the list
(write (substitute 10 7 '(1 5 6 7 8 9 2 7 3 4 5)))
; terminate printing
(terpri)
; find index of 7 in the list
(write (find 7 '(1 5 6 7 8 9 2 7 3 4 5)))
; terminate printing
(terpri)
; find position of 5 in the list
(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

示例

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

main.lisp

; delete odd numbers from the list
(write (delete-if #'oddp '(1 5 6 7 8 9 2 7 3 4 5)))
; terminate printing
(terpri)
; delete even numbers from the list
(write (delete-if #'evenp '(1 5 6 7 8 9 2 7 3 4 5)))
; terminate printing
(terpri)
; remove last even number from the list 
(write (remove-if #'evenp '(1 5 6 7 8 9 2 7 3 4 5) :count 1 :from-end t))
; terminate printing
(terpri)
; set x as vector of characters
(setq x (vector 'a 'b 'c 'd 'e 'f 'g))
; fill x with p starting from 1 to 4 indexes excluding
(fill x 'p :start 1 :end 4)
; print x
(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)

排序和合并序列

排序函数接受一个序列和一个二元谓词,并返回序列的排序版本。

示例

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

main.lisp

; sort and print the list
(write (sort '(2 4 7 3 9 1 5 4 6 3 8) #'<))
; terminate printing
(terpri)
; sort in reverse order and print the list
(write (sort '(2 4 7 3 9 1 5 4 6 3 8) #'>))
; terminate printing
(terpri)

输出

执行代码时,它将返回以下结果:

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

示例

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

main.lisp

; merge two vectors in ascending order and print 
(write (merge 'vector #(1 3 5) #(2 4 6) #'<))
; terminate printing
(terpri)
; merge two lists in ascending order and print 
(write (merge 'list #(1 3 5) #(2 4 6) #'<))
; terminate printing
(terpri)

输出

执行代码时,它将返回以下结果:

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

序列谓词

函数 every、some、notany 和 notevery 被称为序列谓词。

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

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

示例

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

main.lisp

; check if all numbers are even
(write (every #'evenp #(2 4 6 8 10)))
; terminate printing
(terpri)
; check if some numbers are even
(write (some #'evenp #(2 4 6 8 10 13 14)))
; terminate printing
(terpri)
; check if all numbers are even
(write (every #'evenp #(2 4 6 8 10 13 14)))
; terminate printing
(terpri)
; check if any numbers is not even
(write (notany #'evenp #(2 4 6 8 10)))
; terminate printing
(terpri)
; check if all numbers are not even
(write (notevery #'evenp #(2 4 6 8 10 13 14)))
; terminate printing
(terpri)

输出

执行代码时,它将返回以下结果:

T
T
NIL
NIL
T

映射序列

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

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

示例

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

main.lisp

; compute multiple of vectors and print
(write (map 'vector #'* #(2 3 4 5) #(3 5 4 8)))

输出

执行代码时,它将返回以下结果:

#(6 15 16 40)
广告