Reputation: 75740
I'm basically looking for an Elixir equivalent of Ruby's Array#sample
. Something that would let me do this:
list = [1,2,3,4,5,6,7]
sample(list)
#=> 4
sample(list, 3)
#=> [6, 2, 5]
I didn't find anything in the Elixir List Docs either.
Upvotes: 37
Views: 20821
Reputation: 51349
There is no such function in Elixir 1.0, so you need to implement it yourself as mentioned by the other solutions. However, Enum.random/1
is coming with Elixir v1.1: https://hexdocs.pm/elixir/Enum.html#random/1
Upvotes: 12
Reputation: 75740
As José Valim said in his answer, in Elixir 1.1
and above, you can now use these methods to get random element(s) from a list:
Enum.random/1
- For getting single random elementEnum.take_random/2
- For getting multiple random elementsExample:
Enum.random(list) #=> 4
Enum.take_random(list, 3) #=> [3, 9, 1]
Enum.take_random(list, 1) #=> [7]
Remember to call :random.seed(:erlang.now)
first!
I'm still unable to find a 'proper' and 'magical' way to do this, but this is the best I could come up:
For getting a single random element:
list |> Enum.shuffle |> hd
#=> 4
Note: This gives an exception if the list
is empty
For getting multiple random elements:
list |> Enum.shuffle |> Enum.take(3)
#=> [7, 1, 5]
Upvotes: 66
Reputation: 820
If you are running a newer version of Elixir, there's the Enum.take_random/2
function that was added in Elixir v1.1.
From Elixir's v1.1 documentation:
Takes random items from a collection.
Notice this function will traverse the whole collection to get the random sublist of collection. If you want the random number between two integers, the best option is to use the :random module.
So, answering the question, taking multiple items from the list would look like:
list = [1,2,3,4,5,6,7]
Enum.take_random(list, 3)
#=> [2, 4, 1]
Or, for a single item:
list = [1,2,3,4,5,6,7]
Enum.take_random(list, 1)
#=> [1]
Upvotes: 1
Reputation: 713
Another way (for sampling one element only) is:
list |> Enum.at(:random.uniform(length(list)) - 1)
Possibly preferable over the other method if you're working with large enough lists that shuffling the whole list might have a performance impact.
Gazler's comment about using :random.seed(:erlang.now)
still applies.
Upvotes: 5