什么是对地图键进行排序的有效且符合人体工程学的方法?
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 秒。
如何将 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
中的键按插入顺序保存,如
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 秒。