Elixir地图挖掘功能,如Ruby Hash #Dig

时间:2016-05-04 12:56:26

标签: elixir

Ruby中有Hash#Dig的Elixir等价物吗?

Ruby挖掘示例

h = { foo: {bar: {baz: 1}}}

h.dig(:foo, :bar, :baz)           #=> 1
h.dig(:foo, :zot)                 #=> nil

3 个答案:

答案 0 :(得分:11)

使用Kernel.get_in/2

iex(1)> m = %{foo: %{bar: %{baz: 1}}}
%{foo: %{bar: %{baz: 1}}}
iex(2)> get_in m, [:foo, :bar, :baz]
1
iex(3)> get_in m, [:foo, :zot]
nil

答案 1 :(得分:1)

get_in可以正常使用地图。要制作适用于地图和结构的东西,你必须自己制作:

def dig(nil, _), do: nil
def dig(struct, []), do: struct
def dig(struct, [head | tail]) do
  struct
  |> Map.get(head)
  |> dig(tail)
end


> m = %{foo: %{bar: %{baz: 1}}}
> dig m, [:foo, :bar, :baz]
1
> dig m, [:foo, :zot]
nil
> dig m, [:foo, :zot, :qux]
nil

答案 2 :(得分:0)

尽管@Dogbert答案是正确的,但它不适用于they do not implement the Access behavior by default的结构。但是,我需要一种快速简便的方法来在一个测试用例中访问一个GenServer的深层嵌套状态结构(是的,我知道)。下面的模块对我有用:

dig.exs

defmodule Dig do
  def dig(data, [key | keys]) when is_map(data) do
    dig(Map.get(data, key), keys)
  end

  def dig(data, [key | keys]) when is_list(data) do
    dig(Enum.at(data, key), keys)
  end

  def dig(data, []) do
    data
  end
end

用法

import Dig    

some_pid
|> :sys.get_state()
|> dig([:nested, :structure, 0, :some, :value])