Elixir:重命名字典中的键

Rud*_*koŭ 4 dictionary rename key elixir

我有以下地图列表:

[
  %{
    code: "test",
    expired_at: ~U[2020-10-27 17:49:47Z],
  },
  %{
    code: "test",
    expired_at: ~U[2021-07-30 13:54:11Z],
  }
]
Run Code Online (Sandbox Code Playgroud)

将列表中所有地图实体的键重命名code为最复杂的方法是什么?product_code

sba*_*rob 9

可能不是“最复杂的方法”,但我认为一种很好的方法是使用模式匹配,使用带有子句的匿名函数来匹配您想要更改的内容,并且一个用于其他所有内容:

iex> l = [
...>   %{
...>     code: "test",
...>     expired_at: ~U[2020-10-27 17:49:47Z],
...>   },
...>   %{
...>     code: "test",
...>     expired_at: ~U[2021-07-30 13:54:11Z],
...>   }
...> ]
[
  %{code: "test", expired_at: ~U[2020-10-27 17:49:47Z]},
  %{code: "test", expired_at: ~U[2021-07-30 13:54:11Z]}
]
iex> Enum.map(l, &Map.new(&1, fn
...>   {:code, code} -> {:product_code, code}
...>   pair -> pair
...> end))
[
  %{expired_at: ~U[2020-10-27 17:49:47Z], product_code: "test"},
  %{expired_at: ~U[2021-07-30 13:54:11Z], product_code: "test"}
]
Run Code Online (Sandbox Code Playgroud)

请注意,它的使用Map.new/2从给定的可枚举项创建一个 Map,其中包含将给定函数应用于可枚举项所产生的元素

或者,另一种可能更清晰的替代方案是使用and Map.new/2,而不需要像这样使用或迭代映射的键:Map.delete/2Map.put/3

iex> Enum.map(l, fn %{code: code} = element ->
...>   element
...>   |> Map.delete(:code)
...>   |> Map.put(:product_code, code)
...> end)
[
  %{expired_at: ~U[2020-10-27 17:49:47Z], product_code: "test"},
  %{expired_at: ~U[2021-07-30 13:54:11Z], product_code: "test"}
]
Run Code Online (Sandbox Code Playgroud)


Ale*_*kin 6

虽然 @sbacarob 的答案是完全正确的,但如果要更新的主题嵌套得很深,它可能很快就会变得嘈杂。

\n

在这种情况下,提供了一种很棒的、被极度低估的机制来更新嵌套结构,称为Access. 对于这种特殊情况,我们可以使用Kernel.update_in/3withAccess.all/0来获取列表的所有元素。

\n
update_in(\n  list,\n  [Access.all()],\n  &(with {v, m} <- Map.pop(&1, :code),\n    do: Map.put(m, :product_code, v))\n)\n#\xe2\x87\x92 [\n#    %{expired_at: ~U[2020-10-27 17:49:47Z], product_code: "test"},\n#    %{expired_at: ~U[2021-07-30 13:54:11Z], product_code: "test"}\n#  ]\n
Run Code Online (Sandbox Code Playgroud)\n