Elixir:重命名字典中的键
Elixir: rename key in dictionary
我有以下地图列表:
[
%{
code: "test",
expired_at: ~U[2020-10-27 17:49:47Z],
},
%{
code: "test",
expired_at: ~U[2021-07-30 13:54:11Z],
}
]
将列表中所有地图实体的键 code
重命名为 product_code
的最复杂方法是什么?
可能不是“最复杂的方法”,但我认为一个很好的方法是模式匹配,使用一个带有子句的匿名函数来匹配你想要改变的东西,一个用于其他一切:
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"}
]
Notice the use of Map.new/2
which creates a Map from the given enumerable with the elements that result from applying the given function to the enumerable
或者可能更清楚的替代方案,无需像那样使用 Map.new/2
或迭代地图的键,可以使用 Map.delete/2
and Map.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"}
]
虽然@sbacarob 的回答是完全正确的,但如果要更新的主题嵌套很深,它可能很快就会变得嘈杂。
在这种情况下elixir provides a great, extremely underrated mechanism to update nested structures, called Access
. For this particular case, we might use Kernel.update_in/3
with Access.all/0
获取列表的所有元素。
update_in(
list,
[Access.all()],
&(with {v, m} <- Map.pop(&1, :code),
do: Map.put(m, :product_code, v))
)
#⇒ [
# %{expired_at: ~U[2020-10-27 17:49:47Z], product_code: "test"},
# %{expired_at: ~U[2021-07-30 13:54:11Z], product_code: "test"}
# ]
我有以下地图列表:
[
%{
code: "test",
expired_at: ~U[2020-10-27 17:49:47Z],
},
%{
code: "test",
expired_at: ~U[2021-07-30 13:54:11Z],
}
]
将列表中所有地图实体的键 code
重命名为 product_code
的最复杂方法是什么?
可能不是“最复杂的方法”,但我认为一个很好的方法是模式匹配,使用一个带有子句的匿名函数来匹配你想要改变的东西,一个用于其他一切:
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"}
]
Notice the use of
Map.new/2
which creates a Map from the given enumerable with the elements that result from applying the given function to the enumerable
或者可能更清楚的替代方案,无需像那样使用 Map.new/2
或迭代地图的键,可以使用 Map.delete/2
and Map.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"}
]
虽然@sbacarob 的回答是完全正确的,但如果要更新的主题嵌套很深,它可能很快就会变得嘈杂。
在这种情况下elixir provides a great, extremely underrated mechanism to update nested structures, called Access
. For this particular case, we might use Kernel.update_in/3
with Access.all/0
获取列表的所有元素。
update_in(
list,
[Access.all()],
&(with {v, m} <- Map.pop(&1, :code),
do: Map.put(m, :product_code, v))
)
#⇒ [
# %{expired_at: ~U[2020-10-27 17:49:47Z], product_code: "test"},
# %{expired_at: ~U[2021-07-30 13:54:11Z], product_code: "test"}
# ]