collectivelysuperior
Accessing list element with put_in for lists of structs
Let’s say there is a list of structs as a field of a parent struct. Due to the nested nature of the list of maps in the struct, I have been using put_in to insert a new value into the child struct. However, I find myself having to get the index of the child struct in the list and then using that index to access the child struct in the nested list. Is there a better way of doing this? I have searched online and haven’t found much useful info.
In my use case (shown below), the parent struct is a game and the list contains player structs. I am trying to update the player in the list to be the opposite of their current mute boolean.
defmodule Game do
defstruct id: nil, name: nil, password: nil, connected_users: [], messages: []
end
defmodule Player do
defstruct id: nil, muted?: false
end
def mute(%{connected_players: connected_players} = game, player) do
index = Enum.find(connected_players, &(player == &1.id)
game
|> put_in([:connected_players, Access.at!(index), :muted?], not player.muted?)
end
Marked As Solved
thiagomajesk
Hi @collectivelysuperior, welcome to the forum!
I think you can do try something like this:
def mute(%{connected_players: connected_players} = game, %{id: player_id}) do
players = Enum.map(connected_players, fn
{id: ^player_id, muted?: false} = player -> %{player | muted?: true}
player -> player
end
%{game | connected_players: players}
Also Liked
qhwa
I think finding a player by id is quite frequent. For example, when a player joins the game, you also want to make sure you won’t add him/her twice if already in the room.
So I often end up with having the connected_players list as a map, whose keys are ids. Would that be easier for you?
%Game{connected_players: %{"foo" => %Player{id: "foo", ...}}}
shd42
If you want to keep using put_in, you could do it like this (haven’t tested it, but should be fine):
def mute(%Game{} = game, %Player{id: id} = player) do
put_in(game, [
Access.key(:connected_players),
Access.filter(&match?(%{id: ^id}, &1)),
Access.key(:muted?)
], not player.muted?)
end
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









