I have a struct that looks like this:
defmodule WarGame.Core.Game do
defstruct user_cards: [],
croupier_cards: [],
user_bets: [],
bets: [:card_odd, :color_player],
deck: %{},
used: [],
title: nil
def new(fields) do
struct!(__MODULE__, fields)
end
end
I would like to create a function that can take a chosen element of a list bets
and move it to user_bets
. How could I achieve this? There will be only finite (5) elements in this list.
Map.take/2 should do what you need
So you suggest that I change my list to a map and then use Map.take/2
?
Sorry I misread the original post.
Maybe I would do something like this. (it is not the prettiest, but it should work)
index = Enum.find_index(user_cards.bets, &(&1 == :some_term))
{user_bet, bets} = List.pop_at(user_cards.bets, index)
user_bets = [user_bet | user_bets]
%UserCards{user_cards | bets: bets, user_bets: user_bets}
I am not sure that I follow.
In my head I would like to create a function that as an argument takes an element from bets
, uses it to pick this bets
element and inserts it to user_bets
.
Something like this:
`def select_bet(bet) do
finds bet in %WarGame.Core.Game{}.bets
inserts it to %WarGame.Core.Game{}.user_bets
end`
In this case, (I thought you also wanted to remove it from the bets)
def select_bet(%Game{bets: bets} = game, bet) when bet in bets do
%{game | user_bets: [bet | game.user_bets]}
end
def select_bet(game, _bet), do: game
Usually you would want to also pass in the game you are working with in the function.
This will return you a new game with the updated user_bets or the game untouched
2 Likes
Thanks for your time and effort!
When I am trying to run this code I get - (ArgumentError) invalid right argument for operator "in", it expects a compile-time proper list or compile-time range on the right side when used in guard expressions, got: bets
Can also do it like this
def select_bet(%Game{bets: bets} = game, bet) do
if bet in bets do
%{game | user_bets: [bet | game.user_bets]}
else
game
end
end
3 Likes
Thanks for your help, I really appreciate it!
If it’s not too much to ask I would be very grateful if you could explain a bit what you did, as I am having hard time understanding it
Sure, so from the top:
Here we pattern match on the bets inside a game, we could also just done game.bets
inside the if statement.
def select_bet(%Game{bets: bets} = game, bet) do
Inside the function, we have a simple if condition, If we find the bet
item inside the passed in game’s bets list, then we use the shorthand update syntax for a map.
%{map| key: new_value}
We also prepend the bet to the user_bets using the list shorthand syntax, This will give us a new list with the bet at the beginning of the list. It is more efficient to put a new element at the beginning of a list, rather than append to the end, appending to the end requires you to traverse the whole list.
[bet | game.user_bets]
If the If
condition is not true (bet is not found in bets) then we return the game with no modifications
2 Likes
You are the best!
Now I understand what your code meant and will probably be able to do it on my own next time! That’s so helpful!
THANKS!!!
1 Like
Just to add to the answer… bet in bets can be used as a guard clause.
def select_bet(%Game{bets: bets} = game, bet)
when bet in bets, do: %{game | user_bets: [bet | game.user_bets]}
def select_bet(game, _bet), do: game
5 Likes