A quick and hopefully easy question:
I need the means to select from among a given set of hash keys at random. The perl6.org documentation on neither rand nor Hash offer many hints.
my %a = 1,2,3,4,5,6;
Given the above,
%a.keys;
returns (5 1 3)
and if I simply try
%a.rand;
I get a pseudorandom float rather than any one key.
I eventually cobbled together %a.keys[Int(%a.elems.rand)]
, but was hoping for something simpler.
Use pick
or roll
, eg
%a.keys.pick
As always, Christoph's answer is correct (he knows Perl 6 well). However, I thought I'd elaborate a little since pick
and roll
can easily be confused at first.
If you only want one random item, then pick
and roll
seem identical and can be used interchangeably because they both default to returning one item from the original list or array:
my $rand-keyA = %a.keys.pick;
my $rand-keyB = %a.keys.roll;
However, think of them this way:pick
means "Since there are only N things in this container, I can only pick up to N things at once."roll
means "I have an N-sided dice that I can roll as many times as I want."
my %a = 1,2,3,4,5,6; # { 1 => 2, 3 => 4, 5 => 6 }
# (i.e. keys are 1, 3, and 5)
say %a.keys.pick(2); # (5 3)
say %a.keys.pick(2); # (3 1)
say %a.keys.pick(5); # (3 5 1) no more, because there were only three to pick from
say %a.keys.pick(10); # (3 1 5)
say %a.keys.roll(5); # (1 5 1 5 3) as many "rolls" as you request
say %a.keys.roll(10); # (5 5 1 1 5 5 3 1 3 1)
pick(*)
is an easy way to create a randomly reordered list from an array without having to know how many elements it has:
my @array = <foo bar baz foobar>;
@array.pick(*); # (bar foobar baz foo)
roll(*)
is an easy way to create an infinite list whose elements are chosen randomly from the original array:
my @rolls = @array.roll(*);
say @rolls[0]; # foobar
say @rolls[10]; # bar
say @rolls[351]; # baz
say @rolls[19123]; # foobar
say @rolls[1000000]; # bar
say @rolls[1000001]; # bar
say @rolls[1000002]; # foo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With