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

时间:2019-09-23 11:13:29

标签: lisp common-lisp

我想从列表中删除特殊列表。但是功能删除对解决这个问题没有帮助。

它用于列表中的深度搜索,我想将其丢弃。我尝试了删除功能,但是它不起作用。

(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))

1 个答案:

答案 0 :(得分:3)

REMOVE:test关键字参数的默认值(更常见的是接受测试函数参数的函数)为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进行比较。