如果数组元素是唯一的,并且全部是整数或字符串,这里有一个简单的方法来从数组 $array 中选取 $n 个随机*值*(不是键)
<?php array_rand(array_flip($array), $n); ?>
(PHP 4, PHP 5, PHP 7, PHP 8)
array_rand — 从数组中随机选取一个或多个键
从数组中随机选取一个或多个条目,并返回随机条目的键(或键)。
此函数不会生成密码学安全的数值,并且不能用于密码学目的或需要返回值不可猜测的用途。
如果需要密码学安全的随机性,可以使用 Random\Randomizer 和 Random\Engine\Secure 引擎。对于简单的用例,random_int() 和 random_bytes() 函数提供了方便且安全的 API,它由操作系统的 CSPRNG 支持。
array
输入数组。不能为空。
num
指定应选取多少个条目。必须大于零,且小于或等于 array
的长度。
仅选取一个条目时,array_rand() 返回随机条目的键。否则,返回随机条目的键数组。这样做是为了能够从数组中选取随机键以及随机值。如果返回多个键,则它们将按照其在原始数组中出现的顺序返回。
如果 array
为空,或者 num
超出范围,则抛出 ValueError 异常。
版本 | 描述 |
---|---|
8.0.0 |
如果 num 超出范围,array_rand() 现在会抛出 ValueError 异常;以前会引发 E_WARNING 警告,并且函数返回 null 。 |
8.0.0 |
如果 array 为空,array_rand() 现在会抛出 ValueError 异常;以前会引发 E_WARNING 警告,并且函数返回 null 。 |
7.1.0 | 内部随机化算法 已更改,使用 » 梅森旋转算法 随机数生成器,而不是 libc rand 函数。 |
示例 #1 array_rand() 示例
<?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";
?>
如果数组元素是唯一的,并且全部是整数或字符串,这里有一个简单的方法来从数组 $array 中选取 $n 个随机*值*(不是键)
<?php array_rand(array_flip($array), $n); ?>
<?php
/**
* 使用附加检查包装 array_rand 调用
*
* TLDR;不像你希望的那样随机。
*
* 注意:对于 n 参数,越接近输入数组的长度,输出就越不随机。
* 例如:array_random($a, count($a)) == $a 将产生 true
* 这肯定与用于使数组随机化的方法有关(参见其他注释)。
*
* @throws OutOfBoundsException – 如果 n 小于 1 或超过输入数组的大小
*
* @param array $array – 要随机化的数组
* @param int $n – 要返回的元素数量
* @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)]);
}
<?php
// 从 array_rand 获取多个值的示例
$a = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ];
$n = 3;
// 如果你想获取多个值,你可以尝试这样:
print_r( array_intersect_key( $a, array_flip( array_rand( $a, $n ) ) ) );
// 如果你想重新索引键,请将调用包装在'array_values'中:
print_r( array_values( array_intersect_key( $a, array_flip( array_rand( $a, $n ) ) ) ) );
array_rand() 获取随机值,但无法回溯其随机值的选择。
一个简单的例子
我决定混合一个包含10个条目的数组以检索3个值。此选择将给出递增和随机的值。
$myarray = range(1,10);
$pm = array_rand($myarray,3);
// $pm 返回数组(0->0,1->6,2->8)
但是,如果我决定随机排列一个包含10个条目的数组以获取10个条目,array_rand() 将选择为每个返回值分配一个值,因此返回的数组将不是随机的。
$gm = array_rand($myarray,count($myarray));
// $gm 不是随机数组(0->0,1->1,2->2,3->3,4->4,5->5,6->6,7->7,8->8,9->9)
获得真正随机值的最佳方法
要么一次一个值地循环使用 array_rand()
$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);
------------------
或者简单地使用 shuffle() 来真正随机地随机排列数组。
对于加密安全的版本,请尝试
<?php
/**
* 使用加密安全的随机数生成器从数组中获取随机键
* 在 https://codereview.stackexchange.com/questions/275832/cryptographically-secure-version-of-the-core-array-rand-function/ 中讨论和审查
*
* @param array $array
* @throws ValueError 如果数组为空
* @return int|string 键
*/
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";
}
?>
(这是一个改进的版本,与第一个版本不同,它避免了复制*所有*键)