Elixir中如何从嵌套结构生成保留最新元素的字典?
在Elixir中获取每个entity_id的最新视觉事件
Elixir是不可变语言,你用Enum.each遍历的时候,每次修改字典的操作都只是在循环内部生成了一个新字典,外部的原字典根本不会变——这就是你得不到预期结果的原因。要处理这种需要积累结果的场景,正确的姿势是用Enum.reduce,它专门用来在遍历过程中逐步构建新的数据结构。
具体实现步骤
假设你的sorted_slides结构类似这样(已按时间顺序排序,后面的事件为最新):
sorted_slides = [ %{visual_events: [%{entity_id: 1, payload: "aaa"}, %{entity_id: 2, payload: "bbb"}]}, %{visual_events: [%{entity_id: 1, payload: "abc"}, %{entity_id: 3, payload: "def"}]}, %{visual_events: [%{entity_id: 2, payload: "ert"}, %{entity_id: 4, payload: "poi"}]} ]
- 将所有视觉事件扁平为一维列表
用Enum.flat_map提取每个slide里的visual_events,拼成一个无需嵌套的列表:
all_visual_events = sorted_slides |> Enum.flat_map(& &1.visual_events)
- 用
Enum.reduce构建最新事件字典
初始化空字典作为累加器,遍历每个事件时,以entity_id为键存入字典——因为sorted_slides已排序,后续同entity_id的事件会覆盖旧值,最终每个键对应的值就是该实体的最新事件:
latest_events_dict = Enum.reduce(all_visual_events, %{}, fn event, acc -> Map.put(acc, event.entity_id, event) end)
最终结果
运行代码后,latest_events_dict会生成你预期的结构:
%{ 1 => %{entity_id: 1, payload: "abc"}, 2 => %{entity_id: 2, payload: "ert"}, 3 => %{entity_id: 3, payload: "def"}, 4 => %{entity_id: 4, payload: "poi"} }
关键说明
Enum.each仅适用于执行副作用(比如打印日志),无法帮你积累并返回新的数据结构,别用它做这类操作。- Elixir中没有“修改”操作,所有更新都是生成新数据,
Enum.reduce通过持续传递新的累加器,最终帮你构建出目标结构。
内容的提问来源于stack exchange,提问作者Sventies
相关产品推荐
相关产品推荐

