Search code examples
dictionaryelixirkeyrename

Elixir: rename key in dictionary


I have following list of maps:

[
  %{
    code: "test",
    expired_at: ~U[2020-10-27 17:49:47Z],
  },
  %{
    code: "test",
    expired_at: ~U[2021-07-30 13:54:11Z],
  }
]

What is the most sophisticated way to rename key code to product_code for all map entities in the list?


Solution

  • Probably not "the most sophisticated way", but I think a nice way would be with pattern matching, using an anonymous function with a clause to match what you want to change, and one for everything else:

    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

    Or an alternative that might be more clear, without using Map.new/2 like that or iterating over the maps' keys, could be using 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"}
    ]