Clojure有一个函数sorted-set
,可以创建一个PersistentTreeSet
对象。顾名思义,sorted-set
创建了一个排序的唯一对象集合。
什么时候排序集有用?何时使用sorted-set
比sort
和distinct
更好?
=> (apply sorted-set [2 2 1 1 3 3])
#{1 2 3}
=> (sort (distinct [2 2 1 1 3 3]))
(1 2 3)
答案 0 :(得分:2)
当您需要设置语义时,排序集非常有用 - 快速contains?
,conj
和disj
(=元素删除),如Leon所解释的那样 - 以及定义良好的顺序遍历。对于内置有序集(和映射),可以对整个集合(seq
,rseq
)和任何“子范围”(subseq
,{{进行有序遍历。 1}})两个键之间,包括或排他。
如果你愿意接触核心外的集合,那么Contrib库data.avl(我是作者和维护者)提供了一系列排序集和带有附加功能的地图 - {{ 1}}用于按级别访问集合元素,rsubseq
用于发现集合中元素的等级,最近邻居查询,以及返回输入集合的完整功能子集的“子范围”和类似分割的操作(认为nth
返回原始的完整功能子集,而不仅仅是seq,而不是为了GC的目的而保留子集中不存在的原始元素。所有这些都在最坏情况下的O(log n)时间内运行,就像标准的有序集合操作一样。
如果您只需要rank-of
+ subseq
+ contains?
,则可能需要使用哈希集,因为它们往往会为这些操作提供更好的性能。但是,值得注意的是,如果您反对从可能恶意的外部源添加输入到您的集合,即使您不关心订单,您也可能希望使用有序集合。这是因为在存在哈希冲突的情况下哈希集的性能会降低到O(n)(攻击者可以强制使用,使用的哈希函数是确定性的并且事先是固定的),而有序集'O(log n)是很难保证。
如果您只需要对输入集合进行一次排序,然后重复遍历整个或各种前缀/后缀,那么构建独特项目的排序向量可能确实是更好的选择。如果您需要从集合的任意元素(conj
= seq开始的disj
/ subseq
特征,那么即使对于仅限遍历的工作负载,排序集仍然可能更可取。那些rsubseq
的元素,相对于(subseq a-set >= 5)
的排序,它们是> = 5。
答案 1 :(得分:1)
就个人而言,如果我想要一个没有重复的有序数据结构,我会使用有序集合,因为我添加了元素。也就是说,我从一个空集开始,而不是将它应用于列表。
我将使用sort和distinct的时间是,如果我有任何其他数据结构,如我想要订购的列表并删除重复项。
基本上,应用一个集合会为您提供一个具有唯一元素的新对象,而不同的元素会对同一个列表引用起作用。
答案 2 :(得分:1)
有序集与调用sort
和distinct
的结果之间的区别在于结果类型是一个集合。
这为您提供了O(log N)性能(想想二元搜索)以检查元素是否在集合中(contains?
)或添加一个(conj
),而在列表中,由sort
和distinct
返回,默认情况下您会获得更差的特征以实现相同的行为。