如何使用变量来引用结构的键?

时间:2016-08-20 15:36:17

标签: elixir

如何使用变量访问结构的字段:

  var1 = "key1"
  struct1 = %MyStruct{key1: "fdsfd", key2: 33}

  val1 = struct1[:????] # how to use var1 for "key1"?

3 个答案:

答案 0 :(得分:7)

使用String.to_existing_atom/1Map.get/2(因为结构实际上是地图):

iex(1)> defmodule MyStruct do
...(1)>   defstruct [:key1, :key2]
...(1)> end
iex(2)> var1 = "key1"
"key1"
iex(3)> struct1 = %MyStruct{key1: "fdsfd", key2: 33}
%MyStruct{key1: "fdsfd", key2: 33}
iex(4)> val1 = Map.get(struct1, String.to_existing_atom(var1))
"fdsfd"

默认情况下,[:key]语法不适用于结构,因为它使用必须由用户为每个结构实现的Access协议。

如果原子不存在但是使用比将任意输入转换为原子更安全,

String.to_existing_atom/1会抛出一个错误,如果你有一个已经定义了该键的结构,它肯定会存在。有关详细信息,请参阅this question

答案 1 :(得分:1)

Map.get/2之外,您可以模式匹配以获取值,或在结构上实现Access行为,以便您可以在尝试时使用struct1[var1]

(按照建议将var1 = "key1"转换为String.to_existing_atom/1的原子。)

给出struct1 = %MyStruct{key1: "fdsfd", key2: 33}

模式匹配:

iex> %{^var1 => value} = struct1
iex> value
"fdsfd"

访问行为:

defmodule MyStruct do
  defstruct key1: nil, key2: nil

  def fetch(my_struct, key) do
    {:ok, Map.get(my_struct, key)}
  end
end

iex> my_struct[var1]
"fdsfd"

请注意,我没有实现完整的Access行为。见http://elixir-lang.org/docs/stable/elixir/Access.html#callbacks

答案 2 :(得分:1)

如果您使用的是Elixir 1.3或更高版本,则可以在任何结构上使用get_invar1 = "key1" struct1 = %MyStruct{key1: "fdsfd", key2: 33} val1 = get_in struct1, [Access.key!(String.to_existing_atom(var1))]

get_in/3

在Elixir 1.3之前,无法使用get_in/2(查找路径可变的位置),您只能使用val1 = get_in struct1.var1之类的Access.key!KeyError具有工作或提升.image { position: relative; width: 100%; /* for IE 6 */ } h2 { position: absolute; top: 200px; left: 0; width: 100%; } 的好处。