Javascript 如何将有序映射构造为持久数据结构?

Javascript 如何将有序映射构造为持久数据结构?,javascript,functional-programming,tree,trie,Javascript,Functional Programming,Tree,Trie,我有一个基于散列数组映射trie的持久数据结构hamt,它是两个更具体的持久数据结构的基础,例如不可变数组。它提供了一个相当简单的API: const hamtDel = (hamt, props, k) => {/* implementation */} const hamtGet = (hamt, k) => {/* implementation */} const hamtSet = (hamt, props, k, v) => {/* implementation */

我有一个基于散列数组映射trie的持久数据结构
hamt
,它是两个更具体的持久数据结构的基础,例如不可变数组。它提供了一个相当简单的API:

const hamtDel = (hamt, props, k) => {/* implementation */}
const hamtGet = (hamt, k) => {/* implementation */}
const hamtSet = (hamt, props, k, v) => {/* implementation */}
const hamtEmpty = () => {/* implementation */} // creates an empty hamt
hamt
k
v
都是不言自明的
props
只是一种向新生成的
hamt
对象添加任意属性的方法。例如,不可变数组具有附加的
length
offset
属性,以允许高效的
cons
snoc
操作

hamt本身基本上是一张无序的地图。因为有序映射在Javascript中很常见,所以我尝试基于
hamt
实现一个。然而,这是相当困难的。为了跟踪插入顺序,我需要一个用于实际键/值对的
hamt
a
,以及一个用于保存从插入次数到相应键的映射的
B

给定这两种结构,我可以像往常一样访问
A
的元素,并通过检索
B
持有的插入顺序来遍历
A
。但是,当我想在
A
中删除一个元素时,我还需要在
B
中删除它。
B
中的键是插入次数。这意味着在最坏的情况下,我必须遍历整个
B
结构才能找到相应的键

第三个
hamt
B
的键/值对倒置可以缓解问题,但最终得到三个
hamt
以获得有序映射似乎是一个糟糕的设计选择


我非常确信这个问题是众所周知的,并且有可靠的解决方案来解决它。我还没有发现任何有用的东西,因为我缺少合适的术语。非常欢迎您提供这方面的帮助。

在Scala和Kotlin中有一些实现需要查看

首先是scala的
VectorMap
()

它使用压缩哈希数组映射的Trie(也称为CHAMP,类似于HAMT的不可变哈希映射)和向量(基数平衡树)的组合来按顺序存储密钥

接下来是scala的
TreeSeqMap
()

这使用了与VectorMap相同的CHAMP hashmap,但同时使用了一个专门的Trie映射,其中键类似于整数索引,值是有序映射的实际键

接下来是我几个月前写的这个建议的
LinkedHashMap
,它非常类似于一个可变的双链接列表支持的LinkedHashMap,但将链接列表拆分为多个部分,以允许更好的持久更新:


最后,这里还有Kotlin的OrderedMap:这与之前的实现基本相同,只是链接段的长度都是1(即,每个键值都是自己的段,或者换句话说,没有段,只有通过键而不是指针指向前后的单个元素).

您有代码吗?还有一些例子吗?实现有序字典AFAIK的通常方法是存储无序dict和按插入顺序排列的值数组。由于您可以控制实现,因此可以将HAMT与持久化向量结合起来,两者的元素都指向包含的值。@phipsgabler谢谢,我将尝试一下。