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