首页 > 解决方案 > 如何从列表中删除子列表?

问题描述

我想从我的列表中删除一个特殊列表。但是功能 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))

标签: lispcommon-lisp

解决方案


: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

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

但是,如果您使用了两次相同的列表,REMOVE则会按预期工作:

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

上面的示例也可以使用 reader 变量编写如下(结果相似,但整个列表被引用而不是在运行时创建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.


推荐阅读