array_rand
(PHP 4, PHP 5)
array_rand — Выбрать одно или несколько случайных значений из массива
Описание
Использование array_rand() предпочтительно, если вам нужно выбрать одно или несколько случайных значений из массива. Эта функция в качестве параметров берёт массив input и дополнительный аргумент num_req , который определяет количество значений, которое вы хотите выбрать - если не определён, то 1.
Если вы выбираете только одно значение, функция array_rand() возвращает ключ, соответствующий этому значению. В обратном случае, она возвращает массив ключей, соответствующих случайным значениям. Это означает, что вы можете выбрать из массива как случайные значения, так и случайные ключи.
Замечание: Начиная с PHP 4.2.0, больше нет необходимости инициализировать генератор случайных чисел функциями srand() или mt_srand(), поскольку теперь это происходит автоматически.
Пример #1 Пример использования array_rand()
<?php
srand((float) microtime() * 10000000);
$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";
?>
См. также shuffle().
- PHP Руководство
- Функции по категориям
- Индекс функций
- Справочник функций
- Расширения, относящиеся к переменным и типам
- Массивы
- array_change_key_case
- array_chunk
- array_column
- array_combine
- array_count_values
- array_diff_assoc
- array_diff_key
- array_diff_uassoc
- array_diff_ukey
- array_diff
- array_fill_keys
- array_fill
- array_filter
- array_flip
- array_intersect_assoc
- array_intersect_key
- array_intersect_uassoc
- array_intersect_ukey
- array_intersect
- array_key_exists
- array_keys
- array_map
- array_merge_recursive
- array_merge
- array_multisort
- array_pad
- array_pop
- array_product
- array_push
- array_rand
- array_reduce
- array_replace_recursive
- array_replace
- array_reverse
- array_search
- array_shift
- array_slice
- array_splice
- array_sum
- array_udiff_assoc
- array_udiff_uassoc
- array_udiff
- array_uintersect_assoc
- array_uintersect_uassoc
- array_uintersect
- array_unique
- array_unshift
- array_values
- array_walk_recursive
- array_walk
- array
- arsort
- asort
- compact
- count
- current
- each
- end
- extract
- in_array
- key_exists
- key
- krsort
- ksort
- list
- natcasesort
- natsort
- next
- pos
- prev
- range
- reset
- rsort
- shuffle
- sizeof
- sort
- uasort
- uksort
- usort
Коментарии
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); ?>
It doesn't explicitly say it in the documentation, but PHP won't pick the same key twice in one call.
<?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 ) ) ) ) );
<?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)]);
}
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.
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)