Hey! Hope everyone is having a great day.
So, I have an empty map and I want to insert values inside of it. The thing is the keys of the map will be simple integers, however, the values will be sets or MapSet
.
Now, I’ve tried doing these multiple ways using put_in
or update_in
as well as using the built-in functions of Maps. However, it either overwrites the existing value or adds nil
to it. One such example of this is provided below:
values = [[1,2],[2,4],[5,4],[2,3],[1,7],[5,1],[1,2]]
map = values |> Enum.reduce(%{}, fn(v, map) -> put_in(map[Enum.at(v, 0)], MapSet.new([Enum.at(v, 1)])) end)
2 Likes
Are you looking for something like this?
iex> values
|> Enum.with_index()
|> Enum.map(fn {list, index} -> {index, MapSet.new(list)} end)
|> Map.new()
%{
0 => #MapSet<[1, 2]>,
1 => #MapSet<[2, 4]>,
2 => #MapSet<[4, 5]>,
3 => #MapSet<[2, 3]>,
4 => #MapSet<[1, 7]>,
5 => #MapSet<[1, 5]>,
6 => #MapSet<[1, 2]>
}
Edit:
And then to update an entry:
iex> Map.update!(map, key, fn set -> MapSet.put(set, new_value) end)
1 Like
Based on your code, this is what I think you want.
iex(10)> values = [[1,2],[2,4],[5,4],[2,3],[1,7],[5,1],[1,2]]
iex(11)> map =
...(11)> Enum.reduce(values, %{}, fn([k, v], map) ->
...(11)> new_map_set = MapSet.new([v])
...(11)> Map.update(map, k, new_map_set, fn existing_map_set ->
...(11)> MapSet.union(existing_map_set, new_map_set)
...(11)> end)
...(11)> end)
%{1 => #MapSet<[2, 7]>, 2 => #MapSet<[3, 4]>, 5 => #MapSet<[1, 4]>}
My advice is that always try to solve everything with the building blocks of Elixir. in this case Enum.reduce, Enum.reduce_while, Enum.map, list comprehensions, Enum.into, etc.
Once you master them, move onto more abstract stuff such as Kernel.get_and_update_in,
2 Likes