I’m new to Elixir, and relatively new to functional programming. I’ve just written this little algorithm to take a weighted sample from a list of tuples;
# items = [apples: 10, oranges: 30, bananas: 60]
defp weight_based_choice(items) do
max = sum_weights(items)
state = %{
current: 0,
choice: nil,
random_value: Enum.random(1..max)
}
Enum.reduce(items, state, fn item, state ->
weight = elem(item, 1)
state = %{state | current: state[:current] + weight}
choice =
if(state[:random_value] <= state[:current]) do
elem(item, 0)
else
nil
end
if state[:choice] == nil && choice != nil do
%{state | choice: choice}
else
state
end
end)[:choice]
end
defp sum_weights(items) do
Enum.reduce(items, 0, fn item, acc ->
weight = elem(item, 1)
acc + weight
end)
end
Are there more idiomatic ways to do this?