get_in的可选默认值访问行为elixir

时间:2018-02-14 07:03:47

标签: elixir phoenix-framework

是否可以选择在get_in/2中添加默认回退值?

情景:

merge_maps = get_in(
  payload, ["msg", "clicks"]
) ++ get_in(
  payload, ["msg", "opens"]
)

如果在嵌套的"clicks"地图中找不到密钥"opens""msg"get_in/2将返回nil,然后会抛出错误:

** (ArgumentError) argument error
    :erlang.++(nil, nil)
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (iex) lib/iex/evaluator.ex:250: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:230: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:208: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:94: IEx.Evaluator.loop/1
    (iex) lib/iex/evaluator.ex:24: IEx.Evaluator.init/4

能够做类似

的事情会很高兴
get_in(payload, ["msg", "clicks"], [])

如果找不到具有该键的值,则空列表将是后备值。什么是实现这一目标的正确方法?

更新

感谢@PatNowak的回答,我实现了get_in的包装:

defmodule Helpers.AccessHelper do
  def get_in_attempt(data, keys, default \\ []) do
    case get_in(data, keys) do
      nil -> default
      result -> result
    end
  end
end

然后在另一个文件中:

import Helpers.AccessHelper, only: [get_in_attempt: 2]

merge_maps = get_in_attempt(
  payload, ["msg", "clicks"]
) ++ get_in_attempt(
  payload, ["msg", "opens"]
)

3 个答案:

答案 0 :(得分:1)

您可以为Kernel.get_in/2编写自己的包装器,但使用默认值作为后备。

def get_in_attempt(data, keys, default) do
  case get_in(data, keys) do
    nil-> default
    result -> result
  end
end

所以在你的情况下,它足以拥有

def get_in_attempt(data, keys) do
  case get_in(data, keys) do
    nil-> [] # your default is set, so don't need to pass it
    result -> result
  end
end

但是,使用第一种方法(使用显式default参数)更灵活,可以在不同的场景中重复使用。)

答案 1 :(得分:0)

另一种方法,您可以使用SP_names运算符(doc)。

Declare @max varchar(50)
Declare @min varchar(50)
select @min =  min(convert(DATE, date, 104)) from table4
select @max =  max(convert(DATE, date, 104)) from table4
select @max as Recent_Date,@min as Oldest_Date

因此,如果||返回nil,则merge_maps = (get_in( payload, ["msg", "clicks"] ) || [] ) ++ ( get_in( payload, ["msg", "opens"] ) || [] ) 会被选择为默认值

答案 2 :(得分:0)

我认为您想在这种情况下使用Access.key/2Kernel.get_in中的键可以是函数,因此您可以使用Access函数交换出字符串键列表(如果找不到该键,Access.key/2支持默认值)。

类似这样的东西:

get_in(payload, ["msg", Access.key("clicks", []))