【发布时间】:2019-08-07 11:37:20
【问题描述】:
当从 C# 世界迁移到 F#(最惯用的)思维方式时,我发现了这个有趣的区别。
在C#的OOP&mutable世界中,默认的集合集合似乎是HashSet,默认情况下似乎没有排序(因为它接受的比较器只是为了相等);而如果你想要一个排序的,你必须使用SortedSet。
但是在 F# 的世界中,基本的 set 已经排序,因为它需要用于实现相等和比较的元素类型。这有什么具体原因吗?为什么在该语言的主集合中没有无序集?
作为旁注,我想知道是否有可能拥有一个不允许重复的集合,但在将某些元素作为重复项丢弃时优先于某些元素。示例:一条记录 { Name: string; Flag: Option<unit> },因此当插入 { Name = "foo"; Flag = None } 和后来的 { Name = "foo"; Flag = Some() } 时,它最终只包含后一个元素(因为存在 Flag)。
【问题讨论】:
-
C# 没有默认集合。 HashSet 更常见只是因为不需要排序的场景更常见——查找、添加、集合操作。在这些情况下,HashSet 的性能是 O(1),而 SortedSet 和 F# 的集合是
O(logN)。 -
stackoverflow.com/questions/16216439/… 和 stackoverflow.com/questions/28420373/… 可能值得一读。这里的根本区别似乎是可变性 -
HashSet被设计为可变的,因此它的实现针对该场景进行了优化。 F# 没有。 -
@knocte Petricek 的第一个项目符号是实际答案 - HashSet 在内部使用缓冲区,就像列表一样,所以“删除”或添加项目是快速只要你不'不必重新分配缓冲区 - 只需将某些内容写入空闲位置,或“取消标记”它。生成 new (hash)set 的集合操作可能比走两棵树更昂贵,就像 F# 的 set 或 SortedSet 所做的那样。检查例如 F# 的 intersect 实现,intersectAux。本质上,它同时在两棵树上行走
-
我认为错误是用
.net标签标记问题;如果你看一下最接近的选民,他们中的大多数是 C# 人;而一般来说,当我提出 F# 问题并且只标记f#时,我的大多数问题都非常受欢迎,并且我得到了大量高质量的回复;我向 F# 社区致敬