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

时间:2013-10-26 21:40:34

标签: lisp common-lisp membership

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

2 个答案:

答案 0 :(得分:6)

作为Rainer Joswig mentioned in the comments,您不是要检查子集,而是检查成员,您可以使用恰当命名的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

当然,在检查列表中的成员资格时,存在如何将给定项目与列表元素进行比较的问题。 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

答案 1 :(得分: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

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

{{1}}

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