defmodule Example do
# First of all we call map on our keyword
def sample(keyword) when is_list(keyword), do: Enum.map(keyword, &rename/1)
# When key is ok atom and value is a map call rename function
defp rename({key = :ok, map}) when is_map(map), do: {key, rename(map)}
# Rename for maps is using for comprehension changing only key and keeping value as is
defp rename(map) when is_map(map) do
for {key, value} <- map, into: %{}, do: {rename(key), value}
end
# Rename for binary is removing trailing string and calling rename_key
defp rename(binary) when is_binary(binary) do
binary |> String.trim_trailing(" [Required]") |> rename_key()
end
# A simple pattern-match in rename_key for a special email case
defp rename_key("Email Address"), do: "email"
# rename_key for any other string
defp rename_key(key) when is_binary(key) do
key |> String.replace(" ", "") |> Macro.underscore()
end
end
expected_output = [
ok: %{
"email" => "fblue@mikasa.com",
"first_name" => "Blue",
"last_name" => "First"
},
ok: %{
"email" => "sred@mikasa.com",
"first_name" => "Red",
"last_name" => "Second"
},
ok: %{
"email" => "tyellow@mikasa.com",
"first_name" => "Yellow",
"last_name" => "Third"
}
]
input = [
ok: %{
"Email Address [Required]" => "fblue@mikasa.com",
"First Name [Required]" => "Blue",
"Last Name [Required]" => "First"
},
ok: %{
"Email Address [Required]" => "sred@mikasa.com",
"First Name [Required]" => "Red",
"Last Name [Required]" => "Second"
},
ok: %{
"Email Address [Required]" => "tyellow@mikasa.com",
"First Name [Required]" => "Yellow",
"Last Name [Required]" => "Third"
}
]
result = Example.sample(input)
IO.puts(result == expected_output)
# true
The simplest way to accomplish what you’ve written is to look up replacement keys in a supplied map. For instance:
defmodule KeyRenamer do
@key_replacements %{
"First Name [Required]" => "first_name",
"Last Name [Required]" => "last_name",
"Email Address [Required]" => "email"
}
def rename_keys(map) do
Map.new(map, fn k, v ->
new_key = Map.get(@key_replacements, k, k)
{new_key, v}
end
end
end
An alternative approach would be to fix the code that’s generating these keys - for instance, if it’s extracting a value from an HTML label maybe it should be using the input's name or something instead…
I don’t mind being that guy that comments on OLD threads. I ran into a sexy way to rename some keys (or all if you want). I tried googling for it later and couldn’t find it. Google just keep sending me back to this thread. I eventually found the solution in some old code. So, I’m going to dump this solution here so next time I’ll find it faster. (and maybe it will help someone else)
I mixed :keys and “keys” in the example to show it works with both.
good_data should now have the keys latitude, longitude, name, age. It might be cool if Hexdoc had a section showing some common uses that aren’t functions, but indexed like functions. Example “rename_key()” Don’t need the function because you can easily do it like (copy and paste example above)