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
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?
Three different ideas but all very valid. Thank you all!! I like qhwa’s idea of having the connected players a map, which would make accessing the players easier… If I stick with the list, I think the solution by @thiagomajesk is elegant and maintainable, if I ever need to change other fields in the player struct as well. (I didn’t know you could do multiple pattern matches in an anonymous function, cool!!)