flp
I’m trying to manipulate the following map in Elixir, but I fail to get it working. I want to set a user_id for all entries of user_sports.
%{"zip" => "",
"location => "",
"user_sports" =>
%{"0" => %{"sport_id" => "1", "user_id" => ""},
"1" => %{"sport_id" => "1", "user_id" => ""}
}
}
As far as I understood it, the following makes it harder: The keys are “numbers”, so they aren’t stable; it’s not a single entry, there are multiple.
I have tried Map.replace and Map.put, but it feels like the Enum.each prevents the results being saved in the map.
Enum.each(user_sports, fn {k, v} ->
Map.replace!(user_sports, k, %{v | "user_id" => user.id})
end)
When I tried to use them with fixed keys, it worked, but unfortunately, I never know how many entries I have.
Map.put(user_sports, "0", %{Map.get(user_sports, "0") | "user_id" => user.id})
I have also tried get_and_update(_in), but I was always running into the given function must return a two-element tuple or :pop, got: :ok:
params = get_and_update_in(user_params, ["user_sports"], fn c -> Enum.each(c, fn {k, v} -> {k, %{v | "user_id" => user.id}} end) end)
I feel, I am not far way from the right solution, but I have a stupid mistake/misunderstanding.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #elixirconf-eu
- #metaprogramming
- #hex










Showing Posts 11 to 2- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
lkuty
There is a really interesting Hex package named
lens(or on github) which allows to easily perform manipulations of deeply nested maps.Below you’ll find two examples. The first updates
user_idwithout any context (key of current map value) and the second has the context to allow updatinguser_idwith the value of the key (0 or 1).Lens.into/2is used to reconstruct a map out of the list we get fromLens.all/0.jfeng
To expand on what @idi527 said, since data is immutable the way an update works is to have a function return an updated version. So something like
works by returning the updated data and switching the label
datato the new data. The original data is not modified and is still there, until the VM sees that it’s no longer referenced and garbage collects it.Enum.each(enumerable, fun)simply callsfunfor every element of the enumerable, and then returns:ok. This means any value returned byfundoesn’t get used and winds up being garbage collected. The main use forEnum.eachis to call a function with a side-effect, like printing to an IO device or sending a message to another process, for each element.idi527
That’s because most data types in elixir/erlang are immutable. So
Enum.eachwon’t mutateuser_sports.flp
Awesome solutions. Thanks a lot
I feel like I was slowed on the uptake
@idi527: I tried it with Access.fetch too, but unluckily it does not seem to be as flexible as I need to have it
The only thing I still don’t understand is the fact that the following does not work:
Can anyone explain this?
jfeng
If you don’t mind writing a helper function, the logic becomes simpler when you break it into pieces. For instance,
net
Also,
Map.new(enum, fun)can be used instead ofenum |> Enum.map(fun) |> Enum.into(%{}).matteosister
Enum.into(%{})is better imhoidi527
Enum.mapwould return a list of key-value tuples, not a map, so something likeEnum.into(%{})is required for the initial structure to stay intact.Or a reduce function
or a
forcomprehensionBut both of these would be less efficient than a
map.matteosister
One way to do it (not tested):
idi527
I hoped
would also work, but it didn’t.
Access.all()only works with lists: