array_rand

(PHP 4, PHP 5)

array_rand --  从数组中随机取出一个或多个单元

说明

mixed array_rand ( array input [, int num_req] )

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);
print
$input[$rand_keys[0]] . "\n";
print
$input[$rand_keys[1]] . "\n";
?>

参见 shuffle()


add a note add a note User Contributed Notes
dbrooks at icarusstudios dot com
06-Sep-2006 05:28
Instead of looping through all the rows selected to pick a random one, let the server do the work for you:

select * from some_table order by rand() limit 1;
JS
04-Sep-2006 06:07
I wanted to write something that picks a random entry from a 1column-MySQL database - simply Post Of The Moment (potm). I know there surly are many better ways to do it, but I`m rather new to PHP :)  Anyway, it`s simple and no-problem working code.
Of course I assume your DB exists and you always have something in it.

@$link = MySQL_Connect("localhost", "username", "password"); //connect to mysql
mySQL_Select_DB("database"); //..to DB
@$potms = MySQL_Query("SELECT * FROM potm"); //now we get all from our table and store it
MySQL_Close($link); //there`s no need for connection, so we should close it

$potm_array = ''; //sets variables to "zero" values
$i = 0;
while ($entry = MySQL_Fetch_Array($potms)) //now we go through our DB
       {
         $potm_array[$i] = $entry; //our temporary array from which we will random pick a field key
         $i++; //now we increment our field key
       }

$potm_id = array_rand($potw_array); //picks a random key from array
$potm = $potm_array[$potm_id]['name_of_the_field']; //now we have stored our Post Of The Moment in $potm

..hope this helps
mark at rugbyweb dot org
30-Aug-2006 04:29
I was setting up a rotating add banner and was trying to find a way to go about it using an auto_increment id from the database, so I wrote this little script:

<?php
require "mysql.php";
global
$c;
print
"<center>";
$qq=mysql_query("SELECT adID FROM ads WHERE adCLICKS<=adMAX",$c) or die (mysql_error()."<br>Error, please report this error quoting #QAB");
while(
$q=mysql_fetch_array($qq))
{
$ad1[$q['adID']]++; //Used an array and inserted the database query results into it.
}
$ad=array_rand($ad1, 1); //Did a random array function and then used it in the query below.
$er=mysql_query("SELECT * FROM ads WHERE adID='$ad'") or die (mysql_error()."<br>Error, please report this error quoting #QAB3");
if(!
mysql_num_rows($er))
{
print
"<A href='advertise.php'>Place an ad here!</a>";
exit;
}
$r=mysql_fetch_array($er);
print
"<a href='adsout.php?ID={$r['adID']}&BLOCK=1'><img src='{$r['adAD']}' alt='{$r['adNAME']}' height='60' width='468'></a>";
?>
dragonfly at dragonflyeye dot net
08-Jul-2006 04:28
Well, I came up with a workaround for my earlier problem.  For those of you who might need to shuffle around multi-dimensional arrays (I used this to randomize a list of headlines from a MySQL database query), here's what I did to get the desired output:

$subs = //my query went here
$shfl = array_rand($subs, 5);
$shsubs = array();
for ($x=0; $x<count($shfl); $x++) {
   $shsubs[] = $subs[$shfl[$x]];
}

There may in fact be a much easier way to do this, but this is what I came up with and its working!

Thanks to everyone that makes php.net the invaluable tool for us nooobies!
dragonfly at dragonflyeye dot net
07-Jul-2006 10:57
Well, this is interesting.  I don't see anyone else commenting on this, so just in case you were planning to use this function like I was, be prepared: array_rand does not handle multidimensional arrays.  It just ends up returning a list of the X-axis values without the Y-axis arrays.  Bummer.  I'm going to have to find another way to do what I wanted.
steve at webcommons dot biz
06-Jul-2006 05:12
Following are functions for getting a random key or value (or array of random keys or values) from a filtered array.  In other words, given an array of data, these functions filter out what you don't want, then extract a random element or bunch from what's left.

$CallBack is the filtering function. 

  // Utility function for functions below
  function GetRandomArrayValue($TheArray) {
     return $TheArray[array_rand($TheArray)];
  }
 
 
  // Get a random key or array of keys from a filtered array
  function GetRandomFilteredArrayKeys($aInput, $CallBack = NULL, $NumReq = 1) {
     $FilteredKeys = array_keys(array_filter($aInput, $CallBack));
    
     if ($NumReq <= 1) {
       return GetRandomArrayValue($FilteredKeys);
     }
     else {
       shuffle($FilteredKeys);
      
       return array_slice($FilteredKeys, 0, $NumReq);
     }
  }
 
  // Get a random value or array of values from a filtered array
  function GetRandomFilteredArrayValues($aInput, $CallBack = NULL, $NumReq = 1) {
     $aFiltered = array_filter($aInput, $CallBack);
    
     if ($NumReq <= 1) {     
       return $aFiltered[GetRandomArrayValue(array_keys($aFiltered))];
     }
     else {
       shuffle($aFiltered);
      
       return array_slice($aFiltered, 0, $NumReq);
     }
  }
trukin at gmail dot com
17-Mar-2006 05:23
Modify of last note:
<?php
if (!function_exists('array_rand')) {
   function
array_rand($array, $lim=1) {
      
mt_srand((double) microtime() * 1000000);
       for(
$a=0; $a<=$lim; $a++){
          
$num[] = mt_srand(0, count($array)-1);
       }
       return @
$num;
   }
}
?>

mt_rand generates a better random number, and with the limit.
emailfire at gmail dot com
13-Mar-2006 05:32
<?php
if (!function_exists('array_rand')) {
function
array_rand($array) {
srand((double) microtime() * 1000000);
return
rand(0, count($array)-1);
}
}
?>
Will-ster
02-Jan-2006 08:18
This is something I have been playing with for quite awhile. I'm very new to php, but i finally got it to work. it's a function that will take and array[$arrquo] and find a particular keyword[$find] in the different elements of the array then take those elements that posess that keyword and display them at random

<?php
function popbyword($arrquo,$find)
{
$newarr = array('');
 foreach(
$arrquo as $line)
 {
  if(
strstr( $line, $find ) )
  {
  
array_push($newarr, $line);
 
  }
 }   
srand((double)microtime()*1000000);
$rquote = array_rand($newarr);
echo
$newarr[$rquote];
}

popbyword($images, 'Albert');
?>

In my case I had this huge array of quotes with 90 some elements. I was able to find certain keywords in those elements then ONLY display the elements that had those keywords. NEAT! Maybe only because I'm new.
farooqym at ieee dot org
01-Jan-2006 06:05
Here's an algorithm to make a weighted selection of an item from an array.
Say we have an array $items with keys as items and values as corresponding weights.
For example:
<?php
$items
= array(
  
item1 => 3,
  
item2 => 4,
  
item3 => 5,
);
?>
i.e. we want to choose item1 25% of the time, item2 33.3% of the time and item3 41.6% of the time.
Here's a function that works when the weights are positive integers:
<?php
function array_rand_weighted($values) {
  
$r = mt_rand(1, array_sum($values));
   foreach (
$values as $item => $weight) {
       if  (
$r <= $weight) return $item;
      
$r -= $weight;
   }
}
?>
Enjoy!
bjcffnet at gmail dot com
30-Aug-2005 07:29
As wazaawazaa600 at msn dot com pointed out, a multi-dimensional array doesn't work with this function. So, I hope I can help someone with this :)

<?php
/**
 * Returns a number of random elements from an array.
 *
 * It returns the number (specified in $limit) of elements from
 * $array. The elements are returned in a random order, exactly
 * as it was passed to the function. (So, it's safe for multi-
 * dimensional arrays, aswell as array's where you need to keep
 * the keys)
 *
 * @author Brendan Caffrey  <bjcffnet at gmail dot com>
 * @param  array  $array  The array to return the elements from
 * @param  int    $limit  The number of elements to return from
 *                            the array
 * @return array  The randomized array
 */
function array_rand_keys($array, $limit = 1) {
  
$count = @count($array)-1;

  
// Sanity checks
  
if ($limit == 0 || !is_array($array) || $limit > $count) return array();
   if (
$count == 1) return $array;

  
// Loop through and get the random numbers
  
for ($x = 0; $x < $limit; $x++) {
      
$rand = rand(0, $count);

      
// Can't have double randoms, right?
      
while (isset($rands[$rand])) $rand = rand(0, $count);

      
$rands[$rand] = $rand;
   }

  
$return = array();
  
$curr = current($rands);

  
// I think it's better to return the elements in a random
   // order, which is why I'm not just using a foreach loop to
   // loop through the random numbers
  
while (count($return) != $limit) {
      
$cur = 0;

       foreach (
$array as $key => $val) {
           if (
$cur == $curr) {
              
$return[$key] = $val;

              
// Next...
              
$curr = next($rands);
               continue
2;
           } else {
              
$cur++;
           }
       }
   }

   return
$return;
}
?>
alexkropivko at(dog) yandex dot ru
16-Jun-2005 09:21
There was a mistake at "Paul Hodel (paul at ue dot com dot br) 17-Apr-2003 04:40":
String
echo $new_input = $input[$v];

have to be:
echo $new_input[] = $input[$v];
maxnamara at yahoo dot com
13-Mar-2005 07:22
<?php
$input
= array("Neo", "Morpheus", "Trinity", "Cypher", "Tank");

function
my_array_rand($input,$i=2){
srand((float) microtime() * 10000000);

$rand_keys = array_rand($input, $i);

/*
print $input[$rand_keys[0]] . "\n";
print $input[$rand_keys[1]] . "\n";
*/

$res = array();

if(
$i > 1){

for(
$a=0;$a<$i;$a++){

  
$res[] = $input[$rand_keys[$a]];
  
}

}
else{

  
$res[] = $input[$rand_keys];   
  
}

return
$res;
}

$a = my_array_rand($input,3);
echo
"<pre>";
print_r($a);
echo
"</pre>";
?>
yhoko at yhoko dot com
28-Aug-2004 09:16
According to office at at universalmetropolis dot com I have to say that the example is wrong.

<?php
// retrieve one of the options at random from the array
$teamcolours = $teamcolours[rand(0,count($teamcolours))];
?>

The count() function will return the number of items in the array, that's the last index + 1. So if there's 2 items in the array, count() will return 2 but the indices are 0 and 1. Now since rand(x,y) randomizes between x and y inclusively the index from the above example may be out of bounds. Thus you have to subtract 1 from the count:

<?php
  
// Get random item
  
$teamcolours = $teamcolours[rand(0,count($teamcolours)-1)];
?>
leighm at linuxbandwagon dot com leigh morresi
09-Mar-2004 11:36
Another array based password generator, this one is a port from the python mailman version.

this generates slightly predictable but human readable passwords that people can remember
output passwords are for example "rikanumi"

<?php
// port of mailman version
function MakeRandomPassword($length=6) {
$_vowels = array ('a', 'e', 'i', 'o', 'u');   
$_consonants = array ('b', 'c', 'd', 'f', 'g', 'h', 'k', 'm', 'n','p', 'r', 's', 't', 'v', 'w', 'x', 'z');   
$_syllables = array ();   
foreach (
$_vowels as $v) {
   foreach (
$_consonants as $c) {   
      
array_push($_syllables,"$c$v");   
      
array_push($_syllables,"$v$c");
   }
}

for (
$i=0;$i<=($length/2);$i++)        $newpass=$newpass.$_syllables[array_rand($_syllables) ];

return
$newpass;
?>

}
tim dot meader at gsfc dot nasa dot gov
06-Mar-2004 10:31
Just thought I would contribute a password generation function
that uses array_rand. I wrote this because I
could not find anywhere a PHP equivalent of the ability
that the String::Random module in Perl has, which allows
you to specify a schema for how you want the random
string created. In other words: I want 2 Uppercase, 3
lowercase, 2 intergers...etc.  This isn't too comprehensive,
notably it doesn't account for one choosing more itterations
 of a particular type than there are in the array (ie -
choosing more than 10 numbers from output). Additionally,
this doesn't allow for any repeated characters. Hope it can
be of use... comments appreciated.

<?php
  
function &doGeneratePasswords()
   {
      
//////////////////////////////////////
       // lowercase L left out for clarity //
       //////////////////////////////////////
      
$l_achLowercase = array("a","b","c","d","e","f","g","h",
                                
"i","j","k","m","n","o","p","q",
                                
"r","s","t","u","v","w","x",
                                
"y","z");
      
$l_iNumLowercase = count($l_achLowercase);

      
////////////////////////////////////////////
       // uppercase I and O left out for clarity //
       ////////////////////////////////////////////
      
$l_achUppercase = array("A","B","C","D","E","F","G","H",
                                
"J","K","L","M","N","P","Q",
                                
"R","S","T","U","V","W",
                                
"X","Y","Z");
      
$l_iNumUppercase = count($l_achUppercase);

      
$l_aiNumbers = array("1","2","3","4","5","6","7","8","9","0");
      
$l_iNumNumbers = count($l_aiNumbers);

      
$l_achSpecialChars = array("!","#","%","@","*","&");
      
$l_iNumSpecialChars = count($l_achSpecialChars);

      
///////////////////////////////////////////////////////////////////
       // Make sure to create enough blank spaces as you want passwords //
       ///////////////////////////////////////////////////////////////////
      
$l_astPasswds = array("","","","");

      
//////////////////////////////////////////
       // Hopefully these are self explanatory //
       //////////////////////////////////////////
      
$l_astPasswdSchemes = array("SLUUSLNN","LSUNLLNU","NNUSLLSN","LNLSUNLU");

      
$l_iNumPasswds = count($l_astPasswdSchemes);

       for (
$i=0; $i < $l_iNumPasswds; $i++) {
          
$l_iSchemeLength = strlen($l_astPasswdSchemes[$i]);

          
$l_achRandLowercase = array_values(array_rand($l_achLowercase, $l_iNumLowercase));
          
$l_achRandUppercase = array_values(array_rand($l_achUppercase, $l_iNumUppercase));
          
$l_aiRandNumbers = array_values(array_rand($l_aiNumbers, $l_iNumNumbers));
          
$l_achRandSpecialChars = array_values(array_rand($l_achSpecialChars, $l_iNumSpecialChars));

           for (
$j=0; $j < $l_iSchemeLength; $j++) {
              
$l_chCurrentOne = $l_astPasswdSchemes[$i]{$j};

               switch (
$l_chCurrentOne) {
                   case
"L":
                      
$l_astPasswds[$i] .= $l_achLowercase[array_shift($l_achRandLowercase)];
                       break;

                   case
"U":
                      
$l_astPasswds[$i] .= $l_achUppercase[array_shift($l_achRandUppercase)];
                       break;

                   case
"N":
                      
$l_astPasswds[$i] .= $l_aiNumbers[array_shift($l_aiRandNumbers)];
                       break;

                   case
"S":
                      
$l_astPasswds[$i] .= $l_achSpecialChars[array_shift($l_achRandSpecialChars)];
                       break;

                   default:
                       break;
               }
           }
       }

       return
$l_astPasswds;
   }
?>
jpinedo
02-Nov-2003 05:15
An array of arrays example:

<?php
$banners
[0]['imagen']="imagen0.gif";
$banners[0]['url']="www.nosenada.tal";

$banners[1]['imagen']="imagen1.gif";
$banners[1]['url']="www.nose.tal";

$banners[2]['imagen']="imagen2.gif";
$banners[2]['url']="pagina.html";

$banners[3]['imagen']="imagen3.jpg";
$banners[3]['url']="../pagina.php";

$id_banner = array_rand($banners);

echo 
"Archivo:--".$banners[$id_banner]['imagen']. "<br />\n";
echo 
"URL:-----".$banners[$id_banner]['url']. "<br />\n";
?>
wazaawazaa600 at msn dot com
16-Oct-2003 03:24
The function go well ever that you work with a simple array. An array of arrays (also called a table), not works with the function correctly. Example:

<?php
$a
=array(array(0,1),array(1,2),array(2,3),array(3,4),array(4,5));
echo
$a[0][0];echo"<br>";
echo
$a[1][0];echo"<br>";

$b=array_rand($a,2);
echo
$b[0][0];echo"<br>"; //This writes nothing
echo $b[1][0];echo"<br>"; //This writes nothing
?>

If you are in this situation, you will need to make your own solution.
asarnoNOSPAM@interbaun DOT com
24-Jun-2003 02:06
It is correct that using array_rand() with num_req=1 will return an integer and not an array, but why get so complicated with getting just the one value.  The K.I.S.S. method would suggest to do it this way:

<?
srand
((double)microtime() * 10000000);
$originalArray = array("red", "blue", "green", "brown",
"cyan", "magenta", "purle", "cheezy");
$pickOne = array_rand($originalArray, 1);
$aRandomSelection = $originalArray[$pickOne ];
echo
"$aRandomSelection was the random selection made";
?>

You only need to use the foreach if the num_req >=2. In those cases the array_rand() function will return an array of random elements which are a subset of the original array.  When num_req = 1, the array_rand() function returns an integer that signifies a randomly picked key of the original array.  Hope this clarifies things ... it works for me.
c at aufbix dot org
14-Jun-2003 04:31
If you use array_rand with num_req=1, it will return an integer, and not an array as it would in all other circumstances. You can bypass that like this:

<?php
$randelts
=array_rand($feeds,$num);

for (
$j=0;$j<count($randelts);$j++) {
  if (
$num==1) {$subq[$j]=$feeds[$randelts];}
  else {
$subq[$j]=$feeds[$randelts[$i]]}
}
?>
Paul Hodel (paul at ue dot com dot br)
18-Apr-2003 04:40
If you trying to get a randon array just use that... it's easier! And you have no repeats...

<?

srand
((float) microtime() * 10000000);

$input = array ("Neo", "Morpheus", "Trinity", "Cypher", "Tank");

$keys = array_rand ($input, sizeof($input));

while (list(
$k, $v) = each($keys))
{
   echo
$new_input = $input[$v];
}

?>
scandar at home dot se
14-Apr-2003 12:58
Note that the int num_req parameter is the required number of element to randomly select. So if your array has 3 element and num_req=4 then array_rand() will not return anything since it is impossible to select 4 random elements out of an array that only contains 3 elements. Many people think that they will get 3 elements returned but that is of course not the case.
mickoz[at]parodius[dot]com
02-Dec-2002 12:28
For those of you thinking that it does not work for num_req = 1, it is because it return a variable and not an array.  This mainly cause some problem with people using foreach.

The correct way to handle this is explained by that example:

<?php
$some_array
= array("blah","bleh","foo","lele");

$nb_value = 1;

srand ((float) microtime() * 10000000);
$rand_keys = array_rand($some_array, $nb_value);

if(!
is_array($rand_keys))
{
 
$rand_keys = array($rand_keys);
}

print_r($rand_keys); // verify here the array of keys
echo "\n<BR>";
?>

// You can then correctly use the foreach, as it require an array to work
// If you use foreach with one element, it won't work.

<?php
$random_array
= array();

foreach(
$rand_keys as $value)
{
 
array_push($random_array, $some_array[$value]);
}

print_r($random_array);
?>
dboy at jumpstation dot org
23-Jul-2002 09:58
If you just want to pull one random element from an array, try something like this:

<?php
mt_srand
((double) microtime() * 1000000);
$myarray = array("this", "is", "a",
                
"test", "to", "see",
                
"if", "I", "can",
                
"pull", "one", "element",
                
"from", "an", "array",
                
"randomly");
$random_index = mt_rand(0, (count($myarray)-1));
?>

Then to test the randomness or what have you try a simple:

<?php
$string
= ""; // Just to kill the warning
for ($i=0; $i<count($myarray); $i++) {
    
$random_index = mt_rand(0, (count($myarray)-1));
    
$string .= "$myarray[$random_index] ";
}
$string = rtrim($string);
echo (
$string);
?>

I've gotten extremely good output from this method and would recommend it if you're just pulling one element.
josh at 3io dot com
15-Jun-2002 06:20
I modified fake_array_rand to always only return 1 element, and did some benchmarks against calling array_rand with the second parameter as 1.  I ran 100 samples for each function for each number of elements and took the average result.  While the internal array_rand is faster for a small number of elements, it scales very poorly.

1 elements: 2.0619630813599E-05 sec. for array_rand,8.4352493286133E-05 sec. for fake_array_rand
10 elements: 2.1675825119019E-05 sec. for array_rand,8.427619934082E-05 sec. for fake_array_rand
100 elements: 2.9319524765015E-05 sec. for array_rand,8.4599256515503E-05 sec. for fake_array_rand
1000 elements: 0.0001157283782959 sec. for array_rand,8.5572004318237E-05 sec. for fake_array_rand
10000 elements: 0.0016669762134552 sec. for array_rand,8.5201263427734E-05 sec. for fake_array_rand
100000 elements: 0.015599734783173 sec. for array_rand,8.5580348968506E-05 sec. for fake_array_rand
1000000 elements: 0.18011983394623 sec. for array_rand,8.6690187454224E-05 sec. for fake_array_rand

<?php
function fake_array_rand ($array)
{
      
$count = count ($array);
      
# Help keep the number generator random :)
      
$randval and usleep ("0.$randval");

      
# Seed the random number generator
       # Generate a random number
      
srand ((double) microtime() * 10000000);
      
$randval = rand();

      
# Use the random value to 'pick' an entry from the array
       # Count the number of times that the entry is picked
      
++$index[$randval % $count];

       return
$array[$randval % $count];
}
?>
uvm at sun dot he dot net
10-Jul-2001 09:09
If you're just trying to draw a random subset of n elements from an array, it seems more effecient to do something like this:

<?php
function draw_rand_array($array,$draws)
{
      
$lastIndex = count($array) - 1;
      
$returnArr = array();
       while(
$draws > 1)
       {
              
$rndIndex = rand(0,$lastIndex);
              
array_push($returnArr,array_splice($array,$rndIndex,1));
              
$draws--;
              
$lastIndex--;
       }

       return
$returnArr;
}
?>

No messing with indexes when you're done... you just have an array with the elements you're looking for in it.