是否有一个选项可以在 get_in/2
中添加默认的后备值?
方案:
merge_maps = get_in(
payload, ["msg", "clicks"]
) ++ get_in(
payload, ["msg", "opens"]
)
如果在嵌套的"msg"
地图中找不到键"clicks"
或"opens"
,则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"], [])
如果没有找到该键的值,则空列表将是后备值。实现这一目标的正确方法是什么?
update
感谢@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"]
)
您可以为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
参数更灵活,可以在不同的情况下重复使用(。
另一种方式,您可以使用 ||
operator(doc(。
merge_maps = (get_in(
payload, ["msg", "clicks"]
) || [] ) ++ ( get_in(
payload, ["msg", "opens"]
) || [] )
因此,如果 get_in
返回nil,则[]
将被选为默认值
我认为您想在这种情况下使用Access.key/2
。Kernel.get_in
中的键可以是函数,因此您可以将字符串键列表与访问函数交换(如果找不到键,Access.key/2
支持默认值(。
类似的东西:
get_in(payload, ["msg", Access.key("clicks", []))