LISP - 从列表中移除元素
Lisp - 从列表中移除元素
Section titled “Lisp - 从列表中移除元素”Common Lisp 提供了一系列丰富的函数,用于从列表中移除元素。一个关键的区别在于非破坏性函数(返回一个新列表)和破坏性函数(可能会修改原始列表)。理解这一区别对于编写安全可预测的代码至关重要。
非破坏性移除:remove、remove-if、remove-if-not
Section titled “非破坏性移除:remove、remove-if、remove-if-not”非破坏性函数通常更安全,因为它们没有副作用。它们返回一个新列表,而不会触及原始列表。
remove:移除特定项
Section titled “remove:移除特定项”remove 函数创建一个新列表,其中移除了特定项的所有出现。
(defparameter *my-list* '(a b c b a))
;; 移除所有 'b'。原始列表不受影响。(defparameter *new-list* (remove 'b *my-list*))
(format t "原始列表: ~s~%" *my-list*)(format t "新列表: ~s~%" *new-list*)Original List: (A B C B A)New List: (A C A)您可以使用 :count 关键字限制移除的项的数量。
;; 只移除第一个 'b'(print (remove 'b *my-list* :count 1))(A C B A)remove-if:移除符合谓词的元素
Section titled “remove-if:移除符合谓词的元素”remove-if 函数会移除那些给定谓词(一个返回真或假的函数)返回真的元素。
(defparameter *numbers* '(1 2 3 4 5 6))
;; 使用 `evenp` 谓词移除所有偶数。(print (remove-if #'evenp *numbers*))(1 3 5)remove-if-not:移除不符合谓词的元素
Section titled “remove-if-not:移除不符合谓词的元素”相反地,remove-if-not 会移除所有谓词返回假的元素(即,它只保留满足谓词的元素)。
(defparameter *numbers* '(1 2 3 4 5 6))
;; 只保留偶数。(print (remove-if-not #'evenp *numbers*))(2 4 6)使用 :key 和 :test 进行高级筛选
Section titled “使用 :key 和 :test 进行高级筛选”移除函数可以通过 :key 和 :test 关键字参数变得更加强大。
:key:指定一个函数,在对每个元素进行测试之前调用。这对于处理复杂数据结构很有用。:test:指定一个用于比较的函数,而不是默认的eql。
示例:使用 :key
Section titled “示例:使用 :key”;; 一个 (姓名 分数) 对的列表(defparameter *scores* '((alice 88) (bob 95) (charlie 72)))
;; 移除所有名字是 'bob' 的条目(print (remove 'bob *scores* :key #'first))((ALICE 88) (CHARLIE 72))示例:使用 :test
Section titled “示例:使用 :test”(defparameter *numbers* '(10 25 5 40 15))
;; 移除所有大于 20 的数字。;; 测试 #'> 检查元素是否大于项,即元素是否大于 20(print (remove 20 *numbers* :test #'>))(10 5 15)破坏性移除:delete
Section titled “破坏性移除:delete”谨慎使用! delete 系列函数(delete、delete-if 等)允许修改原始列表结构以移除元素。这可能更节省内存,但如果代码的其他部分持有对原始列表的引用,则会很危险。
示例:delete 的效果
Section titled “示例:delete 的效果”;; 注意:我们在这里使用 `defvar` 是因为列表本身将被修改。(defvar *my-list* (list 'a 'b 'c 'b 'a))
(format t "删除前列表: ~s~%" *my-list*)
;; `delete` 返回修改后的列表,但也会改变 *my-list*(delete 'b *my-list*)
(format t "删除后列表: ~s~%" *my-list*)List before delete: (A B C B A)List after delete: (A C A)最佳实践:何时使用破坏性函数
Section titled “最佳实践:何时使用破坏性函数”默认情况下,优先使用 remove 等非破坏性函数。仅在代码的性能关键部分,并且您确定程序的其他部分没有持有对正在修改的列表的引用时,才使用 delete 等破坏性函数。