如何从数组中获取随机值?

156

我有一个名为$ran = array(1,2,3,4);的数组。

我需要从这个数组中随机选择一个值并将其存储在一个变量中,如何实现?

21个回答

280
你也可以只这样做:

$k = array_rand($array);
$v = $array[$k];

如果你有一个关联数组,这是实现它的方法。


11
根据这个评论array_rand函数的随机性不如它应该有的那么高。 - Timo Huovinen
1
或者您可以要求此软件包,并使用array_rand_value - murze
15
自 PHP 7.1 起,array_rand() 使用 Mersenne Twister 生成器:rand() 别名为 mt_rand(),srand() 别名为 mt_srand()。实践中,现在应该足够好了。 - Gras Double

39

8
array_rand函数的第二个参数默认值是1,因此不需要将其写出。 - Nabi K.A.Z.

27
$value = $array[array_rand($array)];

24

你可以使用mt_rand()函数。

$random = $ran[mt_rand(0, count($ran) - 1)];

如果需要该值,这也可以作为一个函数方便使用

function random_value($array, $default=null)
{
    $k = mt_rand(0, count($array) - 1);
    return isset($array[$k])? $array[$k]: $default;
}

4
因为只有4个选项,所以应该使用 mt_rand(0, 3)。不过更正确的做法是:$array[mt_rand(0, count($array))]。 - reko_t
2
哎呀,我想你是指 mt_rand(0, count($ran) - 1)。 - Josh Davis
根据PHP注释,array_rand不够随机,因此建议使用mt_rand - Timo Huovinen
1
整个 isset 部分的意义是什么?这对于关联数组来说无论如何都会失败。 - Luke Cousins
自 PHP 7.1 起,array_rand 函数使用 Mersenne Twister 算法。http://php.net/manual/zh/function.array-rand.php - Jan Richter
显示剩余2条评论

19
您可以使用array_rand函数从数组中选择一个随机的键,如下所示。
$array = array("one", "two", "three", "four", "five", "six");
echo $array[array_rand($array, 1)];

或者你可以使用 rand 和 count 函数来选择一个随机的索引。

$array = array("one", "two", "three", "four", "five", "six");
echo $array[rand(0, count($array) - 1)];

13

另一种通过翻转数组以获取直接值的方法。

代码片段

$array = [ 'Name1' => 'John', 'Name2' => 'Jane', 'Name3' => 'Jonny' ];
$val = array_rand(array_flip($array));

array_rand返回的是键而非值。因此,我们需要将值作为键。

注意: PHP 中的键(key)始终是唯一的,因此当数组进行翻转时,重复的值将被覆盖为一个键。


为什么不直接使用 $array[array_rand($array)]; 呢? - rinogo
@rinogo 这也可以工作,这已经在上面得到了回答。这与您的答案略有不同,array_flip将重复项作为键移除,然后给出结果... 意味着没有重复项! - Shahnawaz Kadari
为了避免重复键,您可以使用以下语法(在第二行):$array = [ 'Name1' => 'John', 'Name2' => 'Jane', 'Name3' => 'Jane' ]; $val = array_rand(array_flip(array_unique($array))); - איש נחמד
我喜欢这种方法,因为它允许在一行简单的代码中直接声明一个数组,例如array_rand(array_flip(array('ad-1.jpg','ad-2.gif','ad-3.png')))。 - undefined

13

这个方法源自 Laravel 的 Collection::random() 方法:

function array_random($array, $amount = 1)
{
    $keys = array_rand($array, $amount);

    if ($amount == 1) {
        return $array[$keys];
    }

    $results = [];
    foreach ($keys as $key) {
        $results[] = $array[$key];
    }

    return $results;
}

用法:

$items = ['foo', 'bar', 'baz', 'lorem'=>'ipsum'];

array_random($items); // 'bar'
array_random($items, 2); // ['foo', 'ipsum']

注意事项:

  • $amount 值必须小于或等于 count($array)
  • array_rand() 函数不会重新排序键名(自 PHP 5.2.10 起,详见 48224),因此选择的项始终按原始顺序排列。如果需要,之后请使用 shuffle() 函数进行重新排序。


文档:array_rand()shuffle()


编辑:自那时以来,Laravel 函数已显著增长,请查看 Laravel 5.4 的 Arr::random()。这里有一些更为详细的内容,源自成熟的 Laravel 函数:

function array_random($array, $number = null)
{
    $requested = ($number === null) ? 1 : $number;
    $count = count($array);

    if ($requested > $count) {
        throw new \RangeException(
            "You requested {$requested} items, but there are only {$count} items available."
        );
    }

    if ($number === null) {
        return $array[array_rand($array)];
    }

    if ((int) $number === 0) {
        return [];
    }

    $keys = (array) array_rand($array, $number);

    $results = [];
    foreach ($keys as $key) {
        $results[] = $array[$key];
    }

    return $results;
}

一些亮点:

  • 如果没有足够的项目可用,则抛出异常
  • array_random($array, 1) 返回一个项目的数组 (#19826)
  • 支持值“0”作为项目数量 (#20439)

10

array_rand函数在处理大型数组时似乎存在一定的不均匀分布问题,因为并不是每个数组项都有同等几率被选中。使用shuffle对数组进行随机排序,然后选择第一个元素就可以解决这个问题:

$myArray = array(1, 2, 3, 4, 5);

// Random shuffle
shuffle($myArray);

// First element is random now
$randomValue = $myArray[0];

这会增加很多额外的计算量,只是为了获取单个随机元素。其他使用 mt_rand() 的答案可能更适合这个任务。 - rinogo
取决于你的需求,我想。在我的情况下,分发非常重要,而计算开销则不是。 - Asciiom

6
$rand = rand(1,4);

或者,特别针对数组:

$array = array('a value', 'another value', 'just some value', 'not some value');
$rand = $array[ rand(0, count($array)-1) ];

2
你永远无法获取此列表中的第一个项目,并且会超出数组范围4。 - Ólafur Waage
第一个 $rand 是关于值的。原始数组的值范围从1到4。第二个 $rand 是关于数组键的,从0到3。 - Josh Davis

6

一句话简述:

echo $array[array_rand($array,1)]

1
虽然这段代码可能回答了问题,但是提供关于为什么和/或如何回答问题的额外上下文可以提高其长期价值。 - β.εηοιτ.βε
这不是与7年前https://dev59.com/wHI-5IYBdhLWcg3w18Z3#19236022的回答相同吗? - Nigel Ren
它在17年被编辑过,但是看起来使用的是相同的方法。 - Sid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接