什么是对地图键进行排序的有效且符合人体工程学的方法?

What is an efficient and ergonomic way to sort the keys of a map?

如何将 Map 的键排序? 我试过了,但它似乎没有内存效率,因为密钥集有三个副本:

sort_map(In) -> sort_map(In, lists:sort(maps:keys(In))).
sort_map(In, Keys) ->
    lists:foldl(
        fun (Key, Out) -> Out#{Key => maps:get(Key, In)} end,
        #{},
        Keys
    ).

更新

这个问题没有意义:不能保证 Map 中的键按插入顺序保存,如 . I'd mis-read something in the Maps EEP.

Erlang 中的映射没有 'publicly' 定义的顺序,因为 "sorted map" 的概念没有什么意义。显然,键在内部有一个顺序,但是你可以通过改变插入的顺序来影响它(当它们有超过 32 个元素时,映射是用哈希数组映射的 Trie 实现的,你有一篇非常有趣的文章 here).

关于内存效率,大的Erlang术语是引用,所以虽然键集被复制,但对于大的Key来说并不是深拷贝。 (除非您将它们发送到其他进程 - 大型二进制文件被引用计数)

我不确定你想在这里实现什么。
您可能想看看 orddicts(虽然它们不是本地实现的),或者实现您自己的结构。

最近我不得不为队列使用 {map(K => _), queue(K)},其中元素可能会在队列中间消失。我使用映射来跟踪队列中的元素并每隔 pop() 检查一个元素是否存在。也许您可以使用类似的方法。

在我的机器上,先将地图转换为列表然后对列表进行排序会更快:

sort_map(In) ->
    lists:keysort(1, maps:to_list(In)).

使用包含 235886 个字符串键的映射,每个键的字符串值与该键相同,您的解决方案在 100 次运行中平均耗时 0.918 秒,而上述解决方案平均耗时 0.573 秒。对于相同大小但具有二进制键和值的映射,平均值分别为 0.494 秒和 0.332 秒。