I would like to give another spin to this proposal:

@doc """
Replaces `old_key` with `new_key` only if `old_key` already exists in `map`.

## Examples

  iex> Map.replace_key(%{a: 1, b: 2}, :a, :c)
  %{c: 1, b: 2}

  iex> Map.replace_key(%{a: 1}, :b, :c)
  %{a: 1}

"""
@spec replace_key(map, key, key) :: map
def replace_key(map, old_key, new_key) do
  case map do
    %{^key => value} ->
      map |> delete(old_key) |> put(new_key, value)

    %{} ->
      map

    other ->
      :erlang.error({:badmap, other})
  end
end

On Monday, October 12, 2020 at 9:37:36 PM UTC+2 ad...@a-corp.co.uk wrote:

> You could compose a function like this:
>
> ```elixir
> def rename_keys(map, key_mapping) do
>   Enum.into(map, %{}, fn {key, value} -> 
>     {Map.fetch(key_mapping, key), value}
>   end)
> end
>
> %{my_map: :is_cool}
> |> rename_keys(%{my_name: :my_new_map})
>
> # => %{my_new_map: :is_cool}
> ```
>
> If you don’t want to put / drop. That way you don’t have to spell out the 
> 99-key map, and it’s easy to pipe together with other functions.
>
> It’s also more efficient than the proposed rename_keys would be as you can 
> rename multiple keys in one pass.
>
> Adam
>
>
> On 12 Oct 2020, at 16:49, jonar...@gmail.com <jonar...@gmail.com> wrote:
>
> > Maybe if you want to keep the other keys as is, then "rename_key" can be 
> handy
>
> This is the use case I had in mind. Let's say I have a map with 100 keys, 
> but only need to rename one of them. In that event, today I would write 
> something like this:
>
> {val, new_map} = Map.pop(original_map, :original_name)
> Map.put(new_map, :new_name, val)
>
> Explicitly defining a new map with 99 keys matching exactly and only one 
> changed would be a very large amount of effort, and brittle. With a 
> Map.rename_key/2 function, I could write the following, which (to Bruce's 
> point) would fit nicely in a pipe chain:
>
> Map.rename_key(original_map, :original_name, :new_name)
>
> > what happens if you add a new key to post? Does it automatically appear 
> in the new_map? Or should it not?
>
> The new key should appear in the new map. The only thing that 
> Map.rename_key/3 (or Map.rename_keys/3) should do is exchange one key for 
> another, without consideration for the rest of the map at all. I enjoy 
> using maps where flexibility is more important than the guarantees that the 
> strictness of structs. If I were converting one struct to another, I would 
> explicitly map each key as in you example above
>
> new_thing = %Thing{
>   user_id: post.author_id,
>   content: post.body,
>   ...
> }
>
> The application of Map.rename_key[s]/3 is more for a proxy application, 
> where data is being shuttled from one place to another with a minor 
> modification. I may or may not know (or care) what the entirety of the map 
> looks like, I simply know that if a given key is present it needs to be 
> replaced with a different one.
> On Monday, October 12, 2020 at 7:25:46 AM UTC-4 José Valim wrote:
>
>> Hi everyone,
>>
>> I thought I had commented on this thread but apparently I have not, so 
>> apologies for the delay.
>>
>> I am not convinced about this functionality because I honestly do not 
>> find this:
>>
>> new_map =
>>   post
>>   |> Map.rename_key(:user_id, :author_id)
>>   |> Map.rename_key(:body, :content)
>>
>> clearer than this:
>>
>> new_map = %{
>>   user_id: post.author_id,
>>   content: post.body,
>>   ...
>> }
>>
>> Maybe if you want to keep the other keys as is, then "rename_key" can be 
>> handy, but even then, what happens if you add a new key to post? Does it 
>> automatically appear in the new_map? Or should it not?
>>
>> Even if we say that "clearer" is personal, there are practical reasons 
>> for preferring the latter, such as the runtime can optimize it better (as 
>> all keys are literals and the map is not built dynamically), and it is 
>> easier to typecheck maps with known keys.
>>
>> So my $.02 here is that this is not something I would necessarily endorse 
>> and, if you really want to rename only certain keys inside a map, you can 
>> do it with a helper function or by using put+drop on the desired keys.
>>
>> Thanks!
>>
>>
> -- 
> You received this message because you are subscribed to the Google Groups 
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to elixir-lang-co...@googlegroups.com.
>
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/elixir-lang-core/a9edf077-9a58-4e51-af54-cd0732b3fbf3n%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/elixir-lang-core/a9edf077-9a58-4e51-af54-cd0732b3fbf3n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/50d9b16d-ddd0-4567-b2bb-bbf6fa7f0ca5n%40googlegroups.com.

Reply via email to