5

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

4

2 回答 2

6

正如 Rainer Joswig在评论中提到的那样,您不是在检查子集,而是检查成员,您可以使用恰当命名的member函数来执行此操作。 Member返回一个广义的布尔值,即,nil为假,而某些东西,不一定t,非nil为真。具体来说,如果一个元素是列表的成员,则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
于 2013-10-28T13:37:20.347 回答
3

如果您想将列表作为您的集合的元素 for 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))给出 NIL。(这可能取决于您的 CL 实现。)如果您想比较 conses 树,tree-equal可以帮助您。

CL-USER 3 > (subsetp '((1) (2) (3)) '((1) (2) (3) (4) (5)) :test #'tree-equal)
T

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

于 2013-10-26T22:31:33.203 回答