You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将两个Elixir Map列表合并为以id为键的单Map

Elixir:合并两个Map列表的简便实现

输入的Map列表

list_one = [
  %{id: :a, value: 1},
  %{id: :b, value: 2},
  %{id: :c, value: 3}
]

list_two = [
  %{id: :a, value: 1},
  %{id: :b, value: 4},
  %{id: :d, value: 5}
]

已知条件

  • 每个列表内的id唯一
  • id始终为原子类型,value始终为整数类型
  • 两个列表可能存在相同的id
  • 每个列表可能包含对方没有的id
  • 所有Map的键数量固定

合并需求

将两个列表合并为一个单Map:

  • 以内部Map的id作为顶层Map的键
  • 对应值需包含两个列表的value,若某列表无对应id则用0填充(该规则可选)

期望输出

%{
  a: %{
    value_one: 1,
    value_two: 1
  },
  b: %{
    value_one: 2,
    value_two: 4
  },
  c: %{
    value_one: 3,
    value_two: 0
  },
  d: %{
    value_one: 0,
    value_two: 5
  }
}

诉求

已知可通过多次Enum.reduce实现,但想寻求更简便的方法。


解决方案

方法一:高效转换法(推荐)

先将两个列表转换为以id为键的Map,再收集所有id生成结果:

# 把列表转成 id => value 的Map
map_one = Enum.into(list_one, %{}, fn %{id: id, value: val} -> {id, val} end)
map_two = Enum.into(list_two, %{}, fn %{id: id, value: val} -> {id, val} end)

# 获取所有唯一的id
all_ids = Map.keys(map_one) ++ Map.keys(map_two) |> Enum.uniq()

# 生成最终结果
result = Enum.into(all_ids, %{}, fn id ->
  {id, %{
    value_one: Map.get(map_one, id, 0),
    value_two: Map.get(map_two, id, 0)
  }}
end)

方法二:管道链式写法

通过合并列表、分组后处理,代码更简洁:

result =
  Enum.concat(list_one, list_two)
  |> Enum.group_by(& &1.id)
  |> Map.new(fn {id, entries} ->
    # 从分组中分别提取两个列表的value,无则用0填充
    value_one = entries |> Enum.find_value(0, fn e -> e in list_one && e.value end)
    value_two = entries |> Enum.find_value(0, fn e -> e in list_two && e.value end)
    {id, %{value_one: value_one, value_two: value_two}}
  end)

注:方法二的e in list_one是线性查找,若列表数据量较大,推荐使用方法一以保证效率。

内容的提问来源于stack exchange,提问作者Agos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 05:30:43