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)
廣告
© . All rights reserved.