我需要类似this的东西,这是一个元素集合,不包含任何元素的重复。 Common Lisp,特别是SBCL,有这样的东西吗?
答案 0 :(得分:6)
对于快速解决方案,只需使用哈希表,如前所述。
但是,如果您更喜欢更有原则的方法,可以查看FSet,它是“功能集理论集合库”。其中,它包含集合和包的类和操作。
(编辑:)最干净的方法可能是将面向集合的操作定义为通用函数。毕竟,一组通用函数基本上等同于Java接口。您可以简单地在标准HASH-TABLE类上实现方法作为第一个原型,并允许其他实现。
答案 1 :(得分:6)
看看cl-containers。有一个集合容器类。
答案 2 :(得分:5)
您可以使用列表,但它们可能被证明对于表示大型集合效率低下。这是使用ADJOIN或PUSHNEW将新元素添加到列表中,而DELETE or 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操作的对应物是:
答案 3 :(得分:5)
是的,它有套装。请参阅 Practical Common Lisp 中的this section on "Sets"。
基本上,您可以使用pushnew
和adjoin
创建一个集合,使用member
,member-if
和member-if-not
进行查询,并将其与其他集合结合使用使用intersection
,union
,set-difference
,set-exclusive-or
和subsetp
等功能。
答案 4 :(得分:2)
使用哈希表轻松解决。
(let ((h (make-hash-table :test 'equalp))) ; if you're storing symbols
(loop for i from 0 upto 20
do (setf (gethash i h) (format nil "Value ~A" i)))
(loop for i from 10 upto 30
do (setf (gethash i h) (format nil "~A eulaV" i)))
(loop for k being the hash-keys of h using (hash-value v)
do (format t "~A => ~A~%" k v)))
输出
0 => Value 0
1 => Value 1
...
9 => Value 9
10 => 10 eulaV
11 => 11 eulaV
...
29 => 29 eulaV
30 => 30 eulaV
答案 5 :(得分:1)
不是我知道的,但你可以使用hash tables来表达相似的东西。
答案 6 :(得分:0)
Lisp哈希表是基于CLOS的。规格here。
答案 7 :(得分:0)
就个人而言,我只会实现一个获取列表并返回唯一集合的函数。我已经起草了一些适合我的东西:
(defun make-set (list-in &optional (list-out '()))
(if (endp list-in)
(nreverse list-out)
(make-set
(cdr list-in)
(adjoin (car list-in) list-out :test 'equal))))
基本上,adjoin
函数会非破坏性地将项目预先添加到列表中,当且仅当项目不在列表中时,接受可选的测试函数(Common Lisp“等于”函数之一) )。您也可以使用pushnew
破坏性地执行此操作,但我发现尾递归实现更加优雅。因此,Lisp确实导出了几个基本函数,允许您将列表用作集合;不需要内置数据类型,因为您可以使用不同的函数将事物添加到列表中。
我所有这些的数据来源(不是功能,而是信息)是Common Lisp HyperSpec和Common Lisp the Language (2nd Edition)的组合。