假设我有两个列表,((1 2 3))
和(((1 2 3)) ((4 5)))
。我希望能够判断第一个列表是否是第二个列表的成员。我曾尝试使用subsetp
,但对于此查询,它不会返回true。我怎么能做到这一点?
答案 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}}
我完全不理解你给出的集合的结构,但我希望这会有所帮助。