PHP 8.3.4 Released!

array_rand

(PHP 4, PHP 5, PHP 7, PHP 8)

array_randPick one or more random keys out of an array

Description

array_rand(array $array, int $num = 1): int|string|array

Picks one or more random entries out of an array, and returns the key (or keys) of the random entries.

Caution

This function does not generate cryptographically secure values, and must not be used for cryptographic purposes, or purposes that require returned values to be unguessable.

If cryptographically secure randomness is required, the Random\Randomizer may be used with the Random\Engine\Secure engine. For simple use cases, the random_int() and random_bytes() functions provide a convenient and secure API that is backed by the operating system’s CSPRNG.

Parameters

array

The input array. Cannot be empty.

num

Specifies how many entries should be picked. Must be greater than zero, and less than or equal to the length of array

Return Values

When picking only one entry, array_rand() returns the key for a random entry. Otherwise, an array of keys for the random entries is returned. This is done so that random keys can be picked from the array as well as random values. If multiple keys are returned, they will be returned in the order they were present in the original array.

Errors/Exceptions

Throws a ValueError if array is empty, or if num is out of range.

Changelog

Version Description
8.0.0 array_rand() now throws a ValueError if num is out of range; previously an E_WARNING was raised, and the function returned null.
8.0.0 array_rand() now throws a ValueError if array is empty; previously an E_WARNING was raised, and the function returned null.
7.1.0 The internal randomization algorithm has been changed to use the » Mersenne Twister Random Number Generator instead of the libc rand function.

Examples

Example #1 array_rand() example

<?php
$input
= array("Neo", "Morpheus", "Trinity", "Cypher", "Tank");
$rand_keys = array_rand($input, 2);
echo
$input[$rand_keys[0]] . "\n";
echo
$input[$rand_keys[1]] . "\n";
?>

See Also

add a note

User Contributed Notes 7 notes

up
92
Anonymous
14 years ago
If the array elements are unique, and are all integers or strings, here is a simple way to pick $n random *values* (not keys) from an array $array:

<?php array_rand(array_flip($array), $n); ?>
up
67
Anonymous
11 years ago
It doesn't explicitly say it in the documentation, but PHP won't pick the same key twice in one call.
up
22
grzeniufication
6 years ago
<?php

/**
* Wraps array_rand call with additional checks
*
* TLDR; not so radom as you'd wish.
*
* NOTICE: the closer you get to the input arrays length, for the n parameter, the output gets less random.
* e.g.: array_random($a, count($a)) == $a will yield true
* This, most certainly, has to do with the method used for making the array random (see other comments).
*
* @throws OutOfBoundsException – if n less than one or exceeds size of input array
*
* @param array $array – array to randomize
* @param int $n – how many elements to return
* @return array
*/
function array_random(array $array, int $n = 1): array
{
if (
$n < 1 || $n > count($array)) {
throw new
OutOfBoundsException();
}

return (
$n !== 1)
?
array_values(array_intersect_key($array, array_flip(array_rand($array, $n))))
: array(
$array[array_rand($array)]);
}
up
10
grzeniufication
6 years ago
<?php
// An example how to fetch multiple values from array_rand
$a = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ];
$n = 3;

// If you want to fetch multiple values you can try this:
print_r( array_intersect_key( $a, array_flip( array_rand( $a, $n ) ) ) );

// If you want to re-index keys wrap the call in 'array_values':
print_r( array_values( array_intersect_key( $a, array_flip( array_rand( $a, $n ) ) ) ) );
up
2
fulachan2 at gmail dot com
2 years ago
array_rand () takes a random value without ever being able to go back in its choice of random value.
A simple example:
I decide to mix an array of 10 entries to retrieve 3 values. This choice will give increasing and random values.

$myarray = range(1,10);

$pm = array_rand($myarray,3);
// $pm return array(0->0,1->6,2->8)

But if I decide to shuffle an array of 10 entries to get 10 entries, array_rand () will choose to assign a value to each return value and therefore the return array will not be random.

$gm = array_rand($myarray,count($myarray));
// $gm not random array(0->0,1->1,2->2,3->3,4->4,5->5,6->6,7->7,8->8,9->9)

The easiest way to have a truly random value:
either use array_rand () in a loop of 1 value at a time

$deg = range(-60,60);
$size = range(16,64);
$color = ["blue","red","green","pink","orange","purple","grey","darkgreen","darkkhaki"];
$i = 0;
$longueur = 10;
do{
++$i;
printf("<span style='transform: rotateZ(%ddeg); display: inline-block;font-size: %spx; color:%s'>%s</span>",
$deg[array_rand($deg)],
$size[array_rand($size)],
$color[array_rand($color)],
$alnum[array_rand($alnum)]);

}while($i < $longueur);

------------------
or simply use shuffle () to shuffle the array really randomly.
up
1
divinity76+spam at gmail dot com
1 year ago
for a cryptographically secure version, try

<?php

/**
* fetch a random key from array, using a cryptograpically secure rng
* discussed+reviewed at https://codereview.stackexchange.com/questions/275832/cryptographically-secure-version-of-the-core-array-rand-function/
*
* @param array $array
* @throws ValueError if array is empty
* @return int|string key
*/
function array_rand_cryptographically_secure(array $array)/*: int|string*/ {
$max = count ( $array ) - 1;
if (
$max < 0) {
throw new
ValueError ( 'Argument #1 ($array) cannot be empty' );
}
return
key ( array_slice ( $array, random_int ( 0, $max ), 1, true ) );
}

$tests = [
[
5, 6, 7],
[
'a' => 1, 'b' => 2, 'c' => 3],
[
'zero', 4 => 'four', 9 => 'nine'],
[
"PEAN"=>0],
[]
];
foreach (
$tests as $test) {
echo
array_rand_cryptographically_secure($test) . "\n";
}

?>
(this is an improved version, which unlike the first version, avoids copying *all* the keys)
up
-8
Vitaly
2 years ago
Generate random index in weights array.
Implementation of Vose's Alias Method.

<?php
class AliasMethod
{
protected
$count;
protected
$prob;
protected
$alias;

public function
__construct($weight)
{
$count = count($weight);
$sum = array_sum($weight);
$d = $count / $sum;
$small = [];
$large = [];

foreach (
$weight as $i => & $w) {
if ( (
$w *= $d) < 1)
$small[] = $i;
else
$large[] = $i;
}
unset(
$w);

$prob = [];
$alias = [];

while (!empty(
$small) AND !empty($large)) {
$l = array_pop($small);
$g = array_pop($large);
$prob[$l] = $weight[$l];
$alias[$l] = $g;

if ( (
$weight[$g] += $weight[$l] - 1) < 1)
$small[] = $g;
else
$large[] = $g;
}

foreach (
$large as $i)
$prob[$i] = 1;

foreach (
$small as $i)
$prob[$i] = 1;

$this->prob = $prob;
$this->alias = $alias;
$this->count = $count;

}

public function
next(): int
{
$i = mt_rand(0, $this->count - 1);
if (
mt_rand() / mt_getrandmax() <= $this->prob[$i])
return
$i;
else
return
$this->alias[$i];
}
}

// Usage:

$weight = [1, 2, 1, 1, 100, 1, 1, 5, 1, 1];
$rnd = new AliasMethod($weight);

$results = array_fill(0, count($weight), 0);

for(
$i = 0; $i < 100000; ++$i) {
$results[$rnd->next()]++;
}
print_r($results);

/*
Array
(
[0] => 901
[1] => 1785
[2] => 899
[3] => 907
[4] => 87655
[5] => 867
[6] => 836
[7] => 4371
[8] => 910
[9] => 869
)
*/
To Top