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

如何在Elixir中对嵌套映射的不存在路径进行更新操作?

在Elixir中使用update_in/put_in更新不存在的嵌套路径

好问题!默认的Kernel.update_in/3和put_in/3确实会在路径中的某个节点不存在时抛出KeyError——因为它们默认假设路径上的每一层结构都已经存在。要实现在不存在的路径上自动创建嵌套结构并完成更新,我们可以借助Elixir的Access行为提供的辅助函数来解决这个问题。

为什么默认方式会报错?

先看一个反例:如果我们尝试更新一个不存在的路径,比如给用户列表添加一个新用户"jane"并更新她的年龄,默认写法会直接报错:

users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
update_in(users, ["jane", :age], &(&1 + 1))
# 抛出 KeyError: key "jane" not found in: %{"john" => %{age: 27}, "meg" => %{age: 23}}

这是因为update_in找不到"jane"这个键对应的结构,无法继续后续的:age路径更新。

解决方法:用Access.key/2指定默认值

Access.key/2是Elixir提供的访问器函数,它的第二个参数可以指定当键不存在时的默认值。更重要的是,当我们用它来构建路径时,update_in/put_in会自动将这个默认值插入到结构中,从而补全缺失的路径节点。

单层缺失路径的处理

比如我们要给不存在的"jane"添加年龄:

users = %{"john" => %{age: 27}, "meg" => %{age: 23}}
update_in(users, [Access.key("jane", %{}), :age], &(&1 + 1))
# 结果:%{"john" => %{age: 27}, "jane" => %{age: 1}, "meg" => %{age: 23}}

这里Access.key("jane", %{})表示:如果"jane"不存在,就用空映射%{}作为默认值。这样update_in就能基于这个空映射继续更新:age,最终"jane"会被自动添加到users中。

多层缺失路径的处理

如果要处理更深层的嵌套路径(比如给"jane"添加profile下的age),只需要给每一层可能缺失的节点都用Access.key/2指定默认值:

users = %{"john" => %{age: 27}}
update_in(users, [
  Access.key("jane", %{}),
  Access.key(:profile, %{}),
  Access.key(:age, 0)
], &(&1 + 1))
# 结果:%{"john" => %{age: 27}, "jane" => %{profile: %{age: 1}}}

这里每一层的默认值确保了路径不会中断,update_in会自动创建所有缺失的嵌套结构。

用put_in处理不存在的路径

对于put_in/3,用法完全一致,只需要替换更新逻辑为直接赋值:

users = %{"john" => %{age: 27}}
put_in(users, [Access.key("jane", %{}), :age], 25)
# 结果:%{"john" => %{age: 27}, "jane" => %{age: 25}}

原理说明

update_in和put_in的路径参数接受任何实现了Access行为的结构。Access.key/2返回的是一个符合Access行为的访问器,它会处理键的存在性:

  • 读取时:如果键不存在,返回指定的默认值
  • 更新时:如果键不存在,会将默认值与更新后的结果合并,自动插入到原结构中

这样就完美解决了"不存在路径的更新"问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:09:43