Reputation: 1036
I'm trying to end up with a single map containing many different preferences, it should look like this:
%{some_preference_name:%{foo:"bar"},another_preference_name:%{foo:"bar"}}
I have a list of preference maps from the database, and I need to get through them and set the "preference" field as the key with the various values as the values map.
I tried to do this with Enum.reduce and Enum,map, but I can't get the list right.
Enum.map(preferences, fn(data)->
Map.put(%{}, data.preference,
%{
foo: data.foo
}
)
end)
returns:
[{some_preference_name:%{foo:"bar"}},{another_preference_name:%{foo:"bar"}}]
then:
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"}
It gets the first one right, but not the rest. I understand that as of Erlang R17, the only way I will be able to add a variable key name is with Map.put/3.
Upvotes: 9
Views: 14637
Reputation: 18090
You can now (since Elixir 1.2.0
) do it without any hacks.
This is listed in the language improvements section in the changes overview.
That is how to do it:
iex> key = :hello
iex> value = "world"
iex> %{key => value}
%{:hello => "world"}
And if you want to pattern match an existing variable - use ^
operator:
iex> key = :hello
iex> %{^key => value} = %{:hello => "another world"}
iex> value
"another world"
Upvotes: 15
Reputation: 3584
Try to use hd()
and tl()
with recursion to get list item instead of Enum.map
and Enum.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
Hope it will be useful for you.
Upvotes: 0
Reputation: 51439
Your code is almost correct, you have just swapped the arguments order in the reduce function:
Enum.reduce(preferences, fn(data, acc)->
Map.put(acc, data.preference, %{foo: data.foo})
end)
Upvotes: 16