【问题标题】:How to put key value pair into map with variable key name如何使用可变键名将键值对放入映射中
【发布时间】:2015-04-24 01:22:38
【问题描述】:

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

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

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

我尝试使用 Enum.reduce 和 Enum,map 执行此操作,但我无法正确获取列表。

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

返回:

[{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)

返回:

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

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

【问题讨论】:

  • 请从数据库中提供您的偏好地图列表。

标签: elixir


【解决方案1】:

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

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

【讨论】:

  • 最终改用 Enum/reduce/3 来填充空地图而不是第一个首选项,尽管 Arkar Aung 的解决方案也有效:-)。我不知道我是怎么把它们混在一起的。顺便说一句,这只是首选,因为它更易于阅读吗?
  • 在我看来,它是首选,因为它更易于阅读,而且它也可以处理许多数据结构。
【解决方案2】:

您现在可以(因为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"

【讨论】:

    【解决方案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
    

    希望对你有用。

    【讨论】:

    • Enum.reduce/3Enum.map/2 通常是首选。您的示例也可以通过最后一个转换子句的模式匹配来改进(convert([h|t], map) 而不是显式调用hdtl)。
    • @JoséValim 啊!!我懂了。谢谢你的建议:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多