在Elixir中,我们可以使用
从嵌套数据结构中获取数据data = %{field: %{other_field: 1}}
data[:field][:other_field]
如果它包含列表,也可以使用
完成data = %{field: %{other_field: [1]}}
get_in data, [:field, :other_field, Access.at(0)]
但是如果给出data.field.other_field是一个结构,那么如何得到这些数据呢?
上述两种方法都会失败,因为结构不会实现Access.fetch/2
。
data = %{field: %{other_field: %Struct{a: 1}}}
那么除了模式匹配之外,访问嵌套结构数据的正确方法是什么?
答案 0 :(得分:4)
使用Access.key/2
:
键(键,默认\\ nil)
访问map / struct中的给定键。
如果密钥不存在或正在访问的值为
nil
,则使用默认值。
iex(1)> defmodule Struct do
...(1)> defstruct [:a]
...(1)> end
iex(2)> data = %{field: %{other_field: %Struct{a: 1}}}
%{field: %{other_field: %Struct{a: 1}}}
iex(3)> get_in data, [:field, :other_field, Access.key(:a)]
1
iex(4)> get_in data, [:field, :other_field, Access.key(:b, :default)]
:default
答案 1 :(得分:1)
为此,我使用了ruby的try运算符的实现。
@spec try(Access.t(), nonempty_list(node) | atom, term) :: term
def try(data, keys, default \\ nil)
def try(nil, _keys, default), do: default
def try(data, keys, default) when is_atom(keys) do
try(data, [keys], default)
end
def try(data, keys, default) when length(keys) == 1 do
get_in(data, [Access.key(hd(keys), default)])
end
def try(data, keys, default) do
get_in(data, [Access.key(hd(keys))])
|> try(tl(keys), default)
end
示例中的用法
try(data, [:field, :other_field, :a]) # with default nil
try(data, [:field, :other_field, :a], 42) # with default 42
try(data, :single_field_as_atom) # with a single value