Erlang 实现列表元素频次统计并将结果存入Map的函数实现问题
Erlang 列表元素频次统计Map实现
- 需求描述:对输入列表内的所有元素做出现频次统计,将元素与对应频次组成键值对存入Erlang Map
- 示例输入:
[rojo, verde, rojo, azul] - 预期输出:
#{rojo => 2, verde => 1, azul => 1}
实现方案
生产可用简洁实现
直接使用Erlang标准库能力完成逻辑,无额外依赖,时间复杂度为O(n),尾递归实现支持任意长度列表,无栈溢出风险:
count_element_frequency(List) -> lists:foldl( fun(Element, FrequencyMap) -> maps:update_with(Element, fun(OldCount) -> OldCount + 1 end, 1, FrequencyMap) end, #{}, List ).
核心逻辑说明
lists:foldl/3从左到右遍历整个列表,初始传入空Map作为状态累加器maps:update_with/4的内置判断逻辑天然匹配频次统计需求:- 如果元素已经在Map中存在,执行更新函数把原有频次+1
- 如果元素不存在,直接写入默认值1作为初始频次
效果验证
传入示例输入调用函数:
count_element_frequency([rojo, verde, rojo, azul]).
返回结果完全匹配预期:#{rojo => 2, verde => 1, azul => 1}
手动尾递归实现(原理参考)
如果需要理解底层遍历流程,可以手动实现和标准库foldl逻辑完全一致的尾递归版本:
count_element_frequency_manual(List) -> count_element_frequency_manual(List, #{}). % 递归终止条件:列表遍历完成,返回最终的频次Map count_element_frequency_manual([], AccMap) -> AccMap; % 递归遍历逻辑 count_element_frequency_manual([CurrentElement | RestList], AccMap) -> % 更新当前元素的频次值 NewAccMap = maps:update_with(CurrentElement, fun(Count) -> Count + 1 end, 1, AccMap), % 递归处理剩余列表,传递更新后的累加Map count_element_frequency_manual(RestList, NewAccMap).
常见踩坑提示
多数人实现该功能卡壳的核心原因,是忽略了Erlang变量不可变的特性:
- 不能在遍历列表时直接修改外部Map变量来累加频次,所有的状态变更必须通过函数返回值逐层传递
- 不要使用
lists:foreach搭配外部变量累加的写法,受不可变变量特性限制,这种写法最终得到的Map永远是初始的空值
内容的提问来源于stack exchange,提问作者Carlos S
相关产品推荐
相关产品推荐

