如何测试一个列表是否是另一个列表的成员

Sur*_*rni 5 lisp membership common-lisp

假设我有两个列表,((1 2 3))并且(((1 2 3)) ((4 5))).我希望能够判断第一个列表是否是第二个列表的成员.我试图使用subsetp,但它不会为此查询返回true.我怎么能做到这一点?

Jos*_*lor 6

正如Rainer Joswig 在评论中提到的那样,你不是要检查子集,而是检查成员,你可以使用恰当命名的member函数来做. Member返回一个通用的布尔值,即,nil对于false,以及某些东西,不一定t是非nil为true.具体来说,如果元素是列表的成员,则member返回列表的尾部,其第一个元素是元素.

CL-USER> (member 3 '(1 2 3 4 5))
(3 4 5)
CL-USER> (member 7 '(1 2 3 4 5))
NIL
Run Code Online (Sandbox Code Playgroud)

当然,在检查列表中的成员资格时,存在如何将给定项目与列表元素进行比较的问题. Member默认比较是eql,它适用于数字之类的东西,如上例所示.但是,对于您的情况,您可能想要测试equal,因为((1 2 3))可能不是与第一个元素相同的对象(((1 2 3)) ((4 5))):

CL-USER> (member '((1 2 3)) '(((1 2 3)) ((4 5))))
NIL
CL-USER> (member '((1 2 3)) '(((1 2 3)) ((4 5))) :test 'equal)
(((1 2 3)) ((4 5)))
CL-USER> (member '((4 5)) '(((1 2 3)) ((4 5))) :test 'equal)
(((4 5)))
CL-USER> (member '((1 2 4)) '(((1 2 3)) ((4 5))) :test 'equal)
NIL
Run Code Online (Sandbox Code Playgroud)


Fra*_*kow 3

如果您希望将列表作为 集合的元素subsetp,则必须更改:test关键字的值。

CL-USER 1 > (subsetp '(1 2 3) '(1 2 3 4 5))
T
CL-USER 2 > (subsetp '((1) (2) (3)) '((1) (2) (3) (4) (5)))
NIL
Run Code Online (Sandbox Code Playgroud)

第一个给出 T,第二个给出 NIL。为什么?因为相等性检查#'eql适用于相同对象或相同值和相同类型的数字。由于两个列表不能是相同的对象,因此(eql '(1) '(1))给出 NIL。(这可能取决于您的 CL 实现。)如果您想比较 cons 树,tree-equal可以帮助您。

CL-USER 3 > (subsetp '((1) (2) (3)) '((1) (2) (3) (4) (5)) :test #'tree-equal)
T
Run Code Online (Sandbox Code Playgroud)

我不完全理解您作为示例给出的集合的结构,但我希望这会有所帮助。