LISP - 合并序列
Lisp - 合并和操作序列
Section titled “Lisp - 合并和操作序列”Common Lisp 提供了一套丰富的函数,用于操作序列(sequences)。序列是元素的有序集合,最常见的两种类型是列表(lists)和向量(vectors)。本章探讨了合并和组合这些序列的现代和惯用方法。
连接序列:通用工具
Section titled “连接序列:通用工具”连接序列最强大和灵活的工具是 concatenate 函数。它可以将多个不同类型的序列合并为一个指定类型的新序列。这避免了手动、易出错的函数。
示例:合并列表、向量和字符串
Section titled “示例:合并列表、向量和字符串”(let ((list1 '(1 2 3)) (vector1 #(4 5 6)) (list2 '(7 8)))
;; 将两个列表连接成一个新列表 (print (concatenate 'list list1 list2)) ;; -> (1 2 3 7 8)
;; 将两个向量连接成一个新向量 (print (concatenate 'vector vector1 #(7 8 9))) ;; -> #(4 5 6 7 8 9)
;; 将一个列表和一个向量连接成一个新向量 (print (concatenate 'vector list1 vector1)) ;; -> #(1 2 3 4 5 6)
;; 连接字符串(字符串是字符向量) (print (concatenate 'string "Hello, " "World!")) ;; -> "Hello, World!")最佳实践:当您需要创建新序列时,优先使用 concatenate 而不是 append。append 专门用于列表,并且效率可能较低,因为它必须复制除最后一个列表参数之外的所有列表。
交错(或称为“压缩”,zipping)是指通过以交替顺序从两个或更多源序列中取出元素来创建新序列。虽然没有一个单一的标准函数可以完成此操作,但可以使用递归或迭代优雅地实现它。
示例:交错两个列表
Section titled “示例:交错两个列表”递归方法简洁明了,并展示了核心列表处理原理。
(defun interleave (list1 list2) "创建一个新列表,交替取自 list1 和 list2 的元素。" (cond ((null list1) list2) ((null list2) list1) (t (list* (first list1) (first list2) (interleave (rest list1) (rest list2))))))
(print (interleave '(a c e) '(b d f g h)));; -> (A B C D E F G H)对于非常长的列表,使用强大的 loop 宏的迭代方法可能更高效,并避免潜在的栈溢出问题。
(defun interleave-iterative (list1 list2) (loop for i in list1 for j in list2 collect i collect j))
(print (interleave-iterative '(a c e) '(b d f)));; -> (A B C D E F);; 注意:基于 loop 的版本在较短列表耗尽时停止。合并已排序序列
Section titled “合并已排序序列”一个常见任务是将两个已排序的序列合并为一个新的、单一的排序序列。执行此操作的惯用且最有效的方法是使用内置的 merge 函数。
示例:合并已排序的数字列表
Section titled “示例:合并已排序的数字列表”(let ((sorted-list1 '(1 5 9)) (sorted-list2 '(2 3 10 12)))
(let ((merged-result (merge 'list sorted-list1 sorted-list2 #'<))) (print merged-result)));; -> (1 2 3 5 9 10 12)merge 函数非常灵活:
- 结果类型:第一个参数指定结果序列的类型(例如,
'list或'vector)。 - 谓词:第四个参数是一个谓词函数(如
#<),用于确定排序顺序。 - 键:它还接受一个
:key参数,用于合并复杂对象的序列,就像sort函数一样。
现代开发工作流
Section titled “现代开发工作流”在实际项目中,您将使用以下工具管理代码:
- ASDF (Another System Definition Facility):用于定义您的项目、其文件及其依赖项。
- Quicklisp:用于下载和管理第三方库。
- Lisp 实现:例如 SBCL (Steel Bank Common Lisp) 以获得高性能,或 CCL (Clozure CL) 以获得快速编译时间。
- 交互式环境:例如带 SLIME 的 Emacs 或带 Alive 的 VS Code,以获得强大的 REPL 驱动开发体验。