我正在尝试将我从OOP概念中获得的想法转换为FP概念,但我不太确定如何最好地实现它。我想拥有多个记录集合,但是在各个集合中都有各自的记录链接。在C#中,我可能会使用多个具有特定于实体的ID的Dictionary对象作为公共密钥,因此,给定任何字典集,方法可以使用其ID /名称提取特定实体。
我想我可以在F#中做同样的事情,因为它的混合特性,但我更喜欢更纯粹的功能。我在这里谈论的最佳结构是什么?
我曾经考虑过可能是trie或patricia trie,但我不需要非常深刻的名字搜索,而且我更有可能拥有一两件事和许多其他事情。这是一个游戏设计理念,例如,你只有一个“玩家”,但可能有大量的“Enemy1”,“Enemy2”等。
FP中的快速键控查找是否有非常好的数据结构,还是应该坚持使用Dictionary / Hashmaps?
答案 0 :(得分:4)
用于表示F#中可用字典的常用功能数据结构是Map
(由larsmans指出)。在封面下,这是作为平行二叉树实现的,因此对于包含 N 元素的树,查找的复杂性为 O(log N)。这比基于散列的字典慢(对于好的散列键有 O(1)),但它允许添加和删除元素而不复制整个集合 - 只需要树的一部分改变。
根据您的描述,我的印象是您只需创建一次数据结构,然后长时间使用它而不进行修改。在这种情况下,您可以实现一个简单的不可变包装器类型,它在封面下使用Dictionary<_, _>
,但是将所有元素作为构造函数中的序列,并且不允许修改:
type ImmutableMap<'K, 'V when 'K : equality>(data:seq<'K * 'V>) = // '
// Store data passed in constructor in hash-based dictionary
let dict = new System.Collections.Generic.Dictionary<_, _>()
do for k, v in data do dict.Add(k, v)
// Provide read-only access
member x.Item with get(k) = dict.[k]
let f = new ImmutableMap<_,_ >( [1, "Hello"; 2, "Ahoj" ])
let str = f.[1]
这应该比使用F#Map
更快,只要您不需要修改集合(或者更准确地说,创建带有添加/删除元素的副本)。
答案 1 :(得分:3)
使用F#模块Collections.Map。我敢打赌,它实现了平衡的二叉搜索树,这是函数式编程中此任务的首选数据结构。
尝试很难编程,并且在搜索引擎索引等专门应用程序中非常有用,它们通常用作数组/数据库/等之上的辅助存储。除非你知道你需要,否则不要使用它们。