elixir - 为什么 Elixir 的 group_by 在实现中使用了反向函数?
问题描述
这是来自Github的 Elixir 的Enum.group_by/3
实现:
def group_by(enumerable, key_fun, value_fun \\ fn x -> x end)
def group_by(enumerable, key_fun, value_fun) when is_function(key_fun) do
reduce(reverse(enumerable), %{}, fn entry, acc ->
key = key_fun.(entry)
value = value_fun.(entry)
case acc do
%{^key => existing} -> Map.put(acc, key, [value | existing])
%{} -> Map.put(acc, key, [value])
end
end)
end
为什么将reverse/1
函数应用于enumerable
?
解决方案
这是为了保留分组项目的顺序。
这是使用标准的示例group_by
:
Enum.group_by(["aa", "ab", "ac", "ba", "bb", "bc"], &String.first/1)
# %{"a" => ["aa", "ab", "ac"], "b" => ["ba", "bb", "bc"]}
如果我们reverse
在自定义实现中删除命令:
Example.no_reverse_group_by(["aa", "ab", "ac", "ba", "bb", "bc"], &String.first/1)
# %{"a" => ["ac", "ab", "aa"], "b" => ["bc", "bb", "ba"]}
您可以看到分组元素的内部顺序"ac", "ab", "aa"
与原始顺序相反"aa", "ab", "ac"
。
原因是因为通过将遇到的每个元素添加到元素列表的前面来Map.put(acc, key, [value | existing])
构建组。与原始可枚举相比,这会以相反的顺序建立项目组。value
existing
添加到列表的速度很快,但添加到列表的末尾需要遍历整个列表。因此,为了使算法能够使用高效的[value | existing]
前置操作,并确保组中项目的顺序与原始可枚举相同,首先需要反转可枚举。
推荐阅读
- python - Python:如何以递归方式将某些内容添加到列表中?
- javascript - 使用 loadsh 过滤器与拼接
- javascript - 在 React with Pagination 中显示图像列表
- arrays - 为什么数组包含我没有指定的值?
- excel - 将 LOOKUP 函数与 <= 和 >= 一起使用
- java - 个人资料图片保存后不显示,它只是显示一个白色的空白屏幕
- java - .so 文件是 64 位而不是 32 位 - Android Studio, Java
- aop - Vertx 横切关注点
- python - 编写秘书问题 (Monte Carlo) - python 代码问题
- scala - 窗口操作后如何收集数据?GroupBy 弄乱了顺序,我得到了不正确的结果