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 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
hubertlepicki
Do you know about Kernel.put_in/2 and Kernel.put_in/3? It might be just what you are looking for.
idi527
I hoped
would also work, but it didn’t.
Access.all()only works with lists:matteosister
One way to do it (not tested):
idi527
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
Enum.into(%{})is better imhonet
Also,
Map.new(enum, fun)can be used instead ofenum |> Enum.map(fun) |> Enum.into(%{}).jfeng
If you don’t mind writing a helper function, the logic becomes simpler when you break it into pieces. For instance,
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?
idi527
That’s because most data types in elixir/erlang are immutable. So
Enum.eachwon’t mutateuser_sports.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.