Elixir:从嵌套结构中提取数据的最佳实践

时间:2016-07-13 23:04:11

标签: elixir

在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}}}

那么除了模式匹配之外,访问嵌套结构数据的正确方法是什么?

2 个答案:

答案 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