How to convert map keys from strings to atoms in Elixir

前端 未结 13 1195
梦毁少年i
梦毁少年i 2021-01-31 07:07

What is the way to convert %{\"foo\" => \"bar\"} to %{foo: \"bar\"} in Elixir?

13条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-01-31 07:37

    I really liked Roman Bedichevskii's answer ... but I needed something that will thoroughly atomize the keys of deeply nested yaml files. This is what I came up with:

       @doc """
       Safe version, will only atomize to an existing key
       """
       def atomize_keys(map) when is_map(map), do: Map.new(map, &atomize_keys/1)
       def atomize_keys(list) when is_list(list), do: Enum.map(list, &atomize_keys/1)
       def atomize_keys({key, val}) when is_binary(key),
         do: atomize_keys({String.to_existing_atom(key), val})
       def atomize_keys({key, val}), do: {key, atomize_keys(val)}
       def atomize_keys(term), do: term
    
       @doc """
       Unsafe version, will atomize all string keys
       """
       def unsafe_atomize_keys(map) when is_map(map), do: Map.new(map, &unsafe_atomize_keys/1)
       def unsafe_atomize_keys(list) when is_list(list), do: Enum.map(list, &unsafe_atomize_keys/1)
       def unsafe_atomize_keys({key, val}) when is_binary(key),
         do: unsafe_atomize_keys({String.to_atom(key), val})
       def unsafe_atomize_keys({key, val}), do: {key, unsafe_atomize_keys(val)}
       def unsafe_atomize_keys(term), do: term
    

    It's main limitation is that if you feed it a tuple {key, value} and the key is a binary, it will atomize it. That is something you want for keyword lists, but it is probably someone's edge case. In any case, YAML and JSON files don't have a concept of a tuple, so for processing those, it won't matter.

提交回复
热议问题