排序集的目的是什么?

时间:2015-11-08 15:22:04

标签: data-structures clojure sortedset

Clojure有一个函数sorted-set,可以创建一个PersistentTreeSet对象。顾名思义,sorted-set创建了一个排序的唯一对象集合。

什么时候排序集有用?何时使用sorted-setsortdistinct更好?

=> (apply sorted-set [2 2 1 1 3 3])
#{1 2 3}
=> (sort (distinct [2 2 1 1 3 3]))
(1 2 3)

3 个答案:

答案 0 :(得分:2)

当您需要设置语义时,排序集非常有用 - 快速contains?conjdisj(=元素删除),如Leon所解释的那样 - 以及定义良好的顺序遍历。对于内置有序集(和映射),可以对整个集合(seqrseq)和任何“子范围”(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)

有序集与调用sortdistinct的结果之间的区别在于结果类型是一个集合。

这为您提供了O(log N)性能(想想二元搜索)以检查元素是否在集合中(contains?)或添加一个(conj),而在列表中,由sortdistinct返回,默认情况下您会获得更差的特征以实现相同的行为。