为什么对F#的默认集合集合进行排序,而对C#却不进行排序?

时间:2019-08-07 11:37:20

标签: c# .net f# set c#-to-f#

从C#世界迁移到F#(最常见的)思维方式时,我发现了这种有趣的差异。

在C#的OOP&mutable世界中,默认的set集合似乎是HashSet,它似乎没有默认排序(因为它接受的比较器仅用于相等性);而如果要排序的话,则必须使用SortedSet

但是,在F#的世界中,基本set已被排序,因为它需要用于实现等式比较的元素类型。有什么具体原因吗?为什么在该语言的主要集合中不设置无序集合?

作为一个旁注,我想知道是否有可能有一个不允许重复的set集合,但是在丢弃某些重复元素时优先于某些元素。示例:记录{ Name: string; Flag: Option<unit> },以便在插入{ Name = "foo"; Flag = None }和以后的{ Name = "foo"; Flag = Some() }时,它最终仅包含后一个元素(因为存在Flag)。

1 个答案:

答案 0 :(得分:2)

F#Set刚好被排序了,但是更多的是实现细节,它是由底层数据结构的选择而产生的,一般不应依赖。

F#集和映射基于AVL树的变体,并且该结构恰好保持了对存储在树中的元素进行排序的不变性。之所以需要比较约束,是因为在此树结构中的查找取决于元素之间的直接比较,以选择要遍历的子树。

但是,这些结构的卖点在于,它们可以用于廉价地实现合理高效,不变的地图和集合版本,而这正是在更广泛的.NET平台不提供任何功能的情况下F#所需要的替代品。

请注意,这并不是在这种情况下唯一可行的选择,JVM函数语言(例如Clojure或Scala)选择了不同的数据结构作为其映射的基础-哈希数组映射的特里-也是不变且持久的,可以说更多实现起来很复杂,对于较大的集合大小,可以说效率更高,但是碰巧会存储无序的元素。与AVL树不同,树的遍历基于哈希,因此不需要比较约束。

因此,如果您已经知道优先级是不变性,那么排序集实际上比未排序集更容易实现。