我需要像这样,元素的集合不包含任何元素的副本.Common Lisp,特别是SBCL,有这样的东西吗?
对于快速解决方案,只需使用哈希表,如前所述.
但是,如果您更喜欢更原则性的方法,可以查看FSet,它是"功能集理论集合库".其中,它包含集合和包的类和操作.
(编辑:)最干净的方法可能是将面向集合的操作定义为泛型函数.毕竟,一组通用函数基本上等同于Java接口.您可以简单地在标准HASH-TABLE类上实现方法作为第一个原型,并允许其他实现.
看看cl-containers.有一个集合容器类.
您可以使用列表,但它们可能被证明对于表示大型集合效率低下.这是使用ADJOIN或PUSHNEW将新元素添加到列表中,并使用DELETE或REMOVE来执行相反操作.
(let ((set (list))) (pushnew 11 set) (pushnew 42 set) (pushnew 11 set) (print set) ; set={42,11} (setq set (delete 42 set)) (print set)) ; set={11}
需要注意的一件事是,这些操作符默认使用EQL来测试集合中的潜在重复项(就像Java使用equals方法一样).对于包含数字或字符的集合,这是可以的,但对于其他对象的集合,应该将诸如EQUAL之类的"更深层次"相等性测试指定为:TEST关键字参数,例如对于一组字符串: -
(let ((set (list))) (pushnew "foo" set :test #'equal) (pushnew "bar" set :test #'equal) (pushnew "foo" set :test #'equal) ; EQUAL decides that "foo"="foo" (print set)) ; set={"bar","foo"}
Lisp与Java的一些Set操作的对应物是:
addAll - > UNION或 NUNION
containsAll - > SUBSETP
removeAll - > SET-DIFFERENCE或NSET-DIFFERENCE
retainAll - > INTERSECTION或NINTERSECTION
是的,它有一套.见的"设置"这一部分,从实用的Common Lisp.
基本上,你可以创建一组同pushnew
和adjoin
,与查询它member
,member-if
并且member-if-not
,与其他组有类似的功能结合起来intersection
,union
,set-difference
,set-exclusive-or
和subsetp
.