Elixir에서 맵 키를 문자열에서 원자로 변환하는 방법
변환하는 방법은 무엇입니까 %{"foo" => "bar"}
로 %{foo: "bar"}
비약으로는?
이해력 사용 :
iex(1)> string_key_map = %{"foo" => "bar", "hello" => "world"}
%{"foo" => "bar", "hello" => "world"}
iex(2)> for {key, val} <- string_key_map, into: %{}, do: {String.to_atom(key), val}
%{foo: "bar", hello: "world"}
이 작업을 수행하는 가장 쉬운 방법은 다음을 사용하는 것입니다 Map.new
.
%{"a" => 1, "b" => 2}
|> Map.new(fn {k, v} -> {String.to_atom(k), v} end)
=> %{a: 1, b: 2}
Enum.reduce / 3 및 String.to_atom / 1 의 조합을 사용할 수 있습니다.
%{"foo" => "bar"}
|> Enum.reduce(%{}, fn ({key, val}, acc) -> Map.put(acc, String.to_atom(key), val) end)
그러나 사용자 입력을 기반으로 원자로 변환하는 것은 가비지 수집되지 않아 메모리 누수가 발생할 수 있으므로주의해야합니다. 이 문제를 참조하십시오 .
아톰이 이미 존재하는 경우이를 방지하기 위해 String.to_existing_atom / 1 을 사용할 수 있습니다 .
@emaillenin의 답변을 기반으로 키가 이미 원자인지 확인하여 이미 원자 인 ArgumentError
키를 가져올 때 String.to_atom에 의해 발생 하는 것을 피할 수 있습니다.
for {key, val} <- string_key_map, into: %{} do
cond do
is_atom(key) -> {key, val}
true -> {String.to_atom(key), val}
end
end
이를위한 라이브러리, https://hex.pm/packages/morphix가 있습니다. 또한 포함 된 키에 대한 재귀 함수도 있습니다.
대부분의 작업은이 함수에서 수행됩니다.
defp atomog (map) do
atomkeys = fn({k, v}, acc) ->
Map.put_new(acc, atomize_binary(k), v)
end
Enum.reduce(map, %{}, atomkeys)
end
defp atomize_binary(value) do
if is_binary(value), do: String.to_atom(value), else: value
end
재귀 적으로 호출됩니다. @Galzer의 답변을 읽은 후 아마도 이것을 String.to_existing_atom
곧 사용하도록 변환 할 것입니다 .
다음은 모듈 형식의 @emaillenin의 답변 버전입니다.
defmodule App.Utils do
# Implementation based on: http://stackoverflow.com/a/31990445/175830
def map_keys_to_atoms(map) do
for {key, val} <- map, into: %{}, do: {String.to_atom(key), val}
end
def map_keys_to_strings(map) do
for {key, val} <- map, into: %{}, do: {Atom.to_string(key), val}
end
end
defmodule Service.MiscScripts do
@doc """
Changes String Map to Map of Atoms e.g. %{"c"=> "d", "x" => %{"yy" => "zz"}} to
%{c: "d", x: %{yy: "zz"}}, i.e changes even the nested maps.
"""
def convert_to_atom_map(map), do: to_atom_map(map)
defp to_atom_map(map) when is_map(map), do: Map.new(map, fn {k,v} -> {String.to_atom(k),to_atom_map(v)} end)
defp to_atom_map(v), do: v
end
m = %{"key" => "value", "another_key" => "another_value"}
k = Map.keys(m)|> Enum.map(&(String.to_atom(&1)))
v = Map.values(m)
result = Enum.zip(k, v) |> Enum.into(%{})
다음은 재귀 적으로 (1) 맵 키를 snakecase로 포맷하고 (2) 원자로 변환하는 데 사용하는 것입니다. 화이트리스트에없는 사용자 데이터는 가비지 수집되지 않으므로 아톰으로 변환 해서는 안됩니다 .
defp snake_case_map(map) when is_map(map) do
Enum.reduce(map, %{}, fn {key, value}, result ->
Map.put(result, String.to_atom(Macro.underscore(key)), snake_case_map(value))
end)
end
defp snake_case_map(list) when is_list(list), do: Enum.map(list, &snake_case_map/1)
defp snake_case_map(value), do: value
참고URL : https://stackoverflow.com/questions/31990134/how-to-convert-map-keys-from-strings-to-atoms-in-elixir
'developer tip' 카테고리의 다른 글
git merge의 기본값을 --no-ff --no-commit으로 만들려면 어떻게해야합니까? (0) | 2020.11.13 |
---|---|
$ (document) .scrollTop ()은 항상 0을 반환합니다. (0) | 2020.11.13 |
내 우분투 도커 이미지에 "ifconfig"명령을 설치하는 방법은 무엇입니까? (0) | 2020.11.13 |
Android WebView 진행률 표시 줄 (0) | 2020.11.13 |
Perl의 STDIN 또는 입력 파일에서 프로그래밍 방식으로 읽기 (0) | 2020.11.13 |