lisp - 如何从列表中删除子列表?

标签 lisp common-lisp

我想从我的列表中删除一个特殊列表。但是函数 remove 并没有帮我解决这个问题。

它用于列表中的深度搜索,我想将其丢弃。我用函数 remove 尝试了它,但它不起作用。

(DEFPARAMETER WB '((HALLWAY EAST OFFICE) (OFFICE WEST HALLWAY) (OFFICE NORTH KITCHEN) (KITCHEN SOUTH OFFICE) (BEDROOM WEST GARDEN) (GARDEN EAST BEDROOM) (GARDEN WEST OFFICE) (OFFICE EAST GARDEN) (GARDEN NORTH BATHROOM) (BATHROOM SOUTH GARDEN) (LAVATORY SOUTH BEDROOM) (BEDROOM NORTH LAVATORY) (LAVATORY WEST BATHROOM) (BATHROOM EAST LAVATORY) (BATHROOM WEST KITCHEN) (KITCHEN EAST BATHROOM) (STUDIO EAST KITCHEN) (KITCHEN WEST STUDIO) (STUDIO SOUTH HALLWAY) (HALLWAY NORTH STUDIO)))

(REMOVE '(BATHROOM EAST KITCHEN) WB) ;should throw (BATHROOM EAST KITCHEN) out of WB but does not work 
(REMOVE '(1 2 3) '((4 5 6) (1 2 3)))
My expected result is ((4 5 6))
But the output is ((4 5 6) (1 2 3))

最佳答案

:test 关键字参数的默认值 REMOVE (更普遍的是接受测试函数参数的函数)是 EQL .

当您编写 (remove '(1 2 3) '((1 2 3) (4 5 6))) 时,您无法保证打印为 ( 1 2 3) 相同。它们很可能由不同的 cons 单元表示:

(eql '(1 2 3) '(1 2 3))
=> NIL

编译器可以在编译时检测到两个列表相等,并使用相同的底层内存,使它们相等,但您通常不能假设情况就是这样。

但是,如果您两次使用相同的列表,REMOVE 将如您所愿地工作:

(let ((a '(1 2 3))) (remove a (list a '(4 5 6))))
=> ((4 5 6))

上面的例子也可以用读取器变量写成如下(结果是相似的,但是整个列表被引用而不是在运行时用 list 创建):

(remove '#1=(1 2 3) '(#1# (4 5 6)))
=> ((4 5 6))

在一般情况下,当您不通过对象的标识来操作对象时,您需要使用知道如何比较列表的测试函数,以便具有相同内容的不同列表被认为是相等的:

(remove '(1 2 3) '((1 2 3) (4 5 6)) :test #'equal)
=> ((4 5 6))

通过上面的代码,将元素与EQUAL进行比较.

关于lisp - 如何从列表中删除子列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58061196/

相关文章:

exception - Common Lisp 错误处理系统中 'store-value' 和 'use-value' 重新启动的语义

memory - 将操作码插入内存

emacs - Emacs Lisp 中的 foldr、foldl 等价物是什么?

haskell - 惰性求值与宏

eclipse - 让 CUSP 在 Eclipse 中工作

lisp - 如何将父类(super class)对象传递给子类构造函数?

common-lisp - 在常见的 lisp 中,我如何格式化浮点并指定分组、群聊和小数分隔符字符

scheme - 将列表的元素配对在一起

lisp - GNU CLISP 中的 if 条件

common-lisp - 如何让 defsystem 使用 "everything"?