是否有任何原生的灵丹妙药方法允许我通过键从地图获取值,无论键是原子还是字符串?像:
a = %{ k: 1 }
b = %{ "k" => 1 }
pure_elixir_method(a, :k) => 1
pure_elixir_method(b, :k) => 1
答案 0 :(得分:3)
通过定义特定的protocol:
,可以实现所需的行为defprotocol IndifferentAccess do
def get(data, key)
end
defimpl IndifferentAccess, for: Map do
def get(data, key) when is_binary(key) do
case Map.fetch(data, key) do
{:ok, value} -> value
:error ->
case Map.fetch(data, String.to_atom(key)) do
{:ok, value} -> value
:error -> :error
end
end
end
end
def get(data, key) when is_atom(key) do
case Map.fetch(data, key) do
{:ok, value} -> value
:error -> get(data, Atom.to_string(key))
end
end
end
a = %{ k: 1 }
b = %{ "k" => 1 }
a |> IndifferentAccess.get(:k)
#⇒ 1
b |> IndifferentAccess.get(:k)
#⇒ 1
但我不会这样做。
答案 1 :(得分:3)
没有。
但你可以编写自己的包装方法来做到这一点:
defmodule MyMap do
def get(map, key) when is_atom(key) do
Map.get(map, key) || Map.get(map, to_string(key))
end
end
像这样使用:
map = %{:a => 1, "b" => 2}
MyMap.get(map, :a) # => 1
MyMap.get(map, :b) # => 2
1.只因为你可以,并不意味着你应该这样做。 %{k: 1, "k" => 2}
是一个很好的例子,为什么你不应该这样做(特别是对于你不了解的数据)。
功能
2.此方法仅适用于atom
个键参数,您可以对其进行修改,使其接受原子和字符串参数:MyMap.get(map, "a") # => 1
功能
3.如果您真的想使用原子获取地图值,请考虑在开始时对地图的键进行符号化。查看我的ExUtils.Map.symbolize_keys/2
。如果您想自己实施,可以get the code here。