如何将键值对放入具有可变键名的映射中

How to put key value pair into map with variable key name

我想最终得到一张包含许多不同偏好的地图,它应该如下所示:

%{some_preference_name:%{foo:"bar"},another_preference_name:%{foo:"bar"}}

我有一个来自数据库的偏好映射列表,我需要通过它们并将 "preference" 字段设置为键,将各种值作为值映射。

我尝试用 Enum.reduce 和 Enum,map 来做到这一点,但我无法获得正确的列表。

Enum.map(preferences, fn(data)->
  Map.put(%{}, data.preference,
   %{
     foo: data.foo
    }
  )
end)

returns:

[{some_preference_name:%{foo:"bar"}},{another_preference_name:%{foo:"bar"}}]

然后:

Enum.reduce(preferences, fn(acc, data)->
  Map.put(acc, data.preference,
   %{
     foo: data.foo
    }
  )
end)

returns:

%{some_preference_name:%{foo:"bar"},preference: "another_preference_name",foo:"bar"}

第一个正确,但其余的不正确。我知道从 Erlang R17 开始,我能够添加变量键名的唯一方法是使用 Map.put/3.

尝试使用 hd()tl() 递归来获取列表项,而不是 Enum.mapEnum.reduce

def get_preference() do
    preferences = [%{:preference => "some_preference_name", :foo => "bar"}, %{:preference => "another_preference_name", :foo => "rab"}]
    convert(preferences, %{})
end

def convert([], map) do
    map
end

def convert([head|tail], map) do
    map = Map.put(map, head.preference, %{foo: head.foo})
    convert(tail, map)
end

希望对你有用。

您的代码几乎是正确的,您刚刚交换了 reduce 函数中的参数顺序:

Enum.reduce(preferences, fn(data, acc)->
  Map.put(acc, data.preference, %{foo: data.foo})
end)

您现在(自 Elixir 1.2.0 起)无需任何技巧即可完成。 这在 the changes overview.

的语言改进部分中列出

这是怎么做的:

iex> key = :hello
iex> value = "world"
iex> %{key => value}
%{:hello => "world"}

如果您想模式匹配现有变量 - 使用 ^ 运算符:

iex> key = :hello
iex> %{^key => value} = %{:hello => "another world"}
iex> value
"another world"