search for in the  
<rsortsizeof>
Last updated: Thu, 19 May 2005

shuffle

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

shuffle -- Shuffle an array

Description

bool shuffle ( array &array )

This function shuffles (randomizes the order of the elements in) an array.

Example 1. shuffle() example

<?php
$numbers
= range(1, 20);
srand((float)microtime() * 1000000);
shuffle($numbers);
while (list(,
$number) = each($numbers)) {
   echo
"$number ";
}
?>

Note: As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand() as this is now done automatically.

See also arsort(), asort(), ksort(), rsort(), sort(), and usort().



User Contributed Notes
shuffle
berndt at www dot michael - berndt dot de
08-May-2005 02:18
randomize an assoziativ array with shuffle ()
http://www.michael-berndt.de/ie/tux/zufall_array_assoziativ.htm
berndt at michael - berndt dot de
17-Apr-2005 08:59
create secure passwords with shuffle()
http://www.michael-berndt.de/ie/tux/secure_password.htm
monte at ohrt dot com
21-Mar-2005 04:10
This is an attempt to get the Fisher Yates shuffle right, and as optimized as possible. The array items are stepped through from last to first, each being swapped with another between itself and the beginning of the array (N-1 shuffles required.) Using list() to swap array vars instead of a tmp var proved to be slightly slower. Testing for $i = $j decreases performance as the array size increases, so it was left out (elements are always swapped.)

function fisherYatesShuffle(&$items)
{
   for ($i = count($items) - 1; $i > 0; $i--)
   {
     $j = @mt_rand(0, $i);
     $tmp = $items[$i];
     $items[$i] = $items[$j];
     $items[$j] = $tmp;
   }
}
Vladimir Kornea of typetango.com
25-Oct-2004 04:06
shuffle() does not maintain key associations. This is how to shuffle an associative array without losing key associations:

<?php
function shuffle_me($shuffle_me) {
  
$randomized_keys = array_rand($shuffle_me, count($shuffle_me));
   foreach(
$randomized_keys as $current_key) {
      
$shuffled_me[$current_key] = $shuffle_me[$current_key];
   }
   return
$shuffled_me;
}
?>

This is simpler than the other methods described here and it actually works.
al at giicorp dot com
20-Oct-2004 07:33
When shuffling large sets this got a faster response, since $array is always the same size, those extra millisecs counts.

function fisherYatesShuffle(&$array)
{
   $total = count($array);// <--
   for ($i = 0; $i<$total; $i++)
   {
         $j = @mt_rand(0, $i);
         $temp = $array[$i];
         $array[$i] = $array[$j];
         $array[$j] = $temp;
   }
}
Bjorn AT smokingmedia DOT com
23-Sep-2004 07:02
To shuffle an associated array and remain the association between keys and values, use this function:

<?php

$test_array
= array("first" => 1,"second" => 2,"third" => 3,"fourth" => 4);

function
shuffle_assoc($input_array){

   foreach(
$input_array as $key => $value){
    
$temp_array[$value][key] = $key;
     }

  
shuffle($input_array);

   foreach(
$input_array as $key => $value){
    
$return_array[$temp_array[$value][key]] = $value;
     }

   return
$return_array;
   }

echo
"<pre>";
print_r(shuffle_assoc($test_array));
echo
"</pre><hr />";

// this will output something like this:
/*
Array
(
   [fourth] => 4
   [second] => 2
   [third] => 3
   [first] => 1
)

*/
?>
bryan at mcnett dot org
20-Apr-2004 05:35
The technique described in the following article enables visiting each in a range of integers exactly once, but in perceptually random order. A reprint of this article appears in Graphics Gems:

http://www.mactech.com/articles/mactech/Vol.06/06.12/SafeDissolve/

It's possible to cheaply permute the order of integers so produced with XOR et al. This may enable random shuffling of arrays with less guarantee of true randomness, but more guarantee that the output looks different from the input, which is probably what you want.

The above technique belongs to the family of LFR (Linear Feedback Registers), which have a long history of providing "enough randomness" at very low cost.
Justin Knoll
15-Apr-2004 07:24
This code is very appealing in its simplicity and speed, but it's not a random shuffle:

<?php
function randomcmp($a, $b)
{
  return
mt_rand(-1, 1);
}

function
swapshuffle(&$array)
{
 
srand((double) microtime() * 10000000);
 
uksort($array, "randomcmp");
}
?>

This is because uksort calls the C function zend_qsort and this quicksorts the array using the provided comparision function. The pairs of indices selected are biased by the nature of the quicksort algorithm.

One effect is that an element in the middle of the array is heavily biased toward being "shuffled" to the middle. Elements on the edges are biased towards the edges; they're likely to switch edges, but unlikely to end up in the middle.
injunjoel
11-Mar-2004 09:27
Be aware that when shuffling an associative array your associative keys will be lost! example below:
<?php
echo "before shuffle\n";
$numbers = array('first'=>1,'second'=>2,'third'=>3,'fourth'=>4);
foreach(
$numbers as $key=>$value){
   echo
"$key => $value\n";
}
echo
"\nafter shuffle\n";
srand((float)microtime() * 1000000);
shuffle($numbers);

foreach(
$numbers as $key=>$value){
   echo
"$key => $value\n";
}

?>
--output--
before shuffle
first => 1
second => 2
third => 3
fourth => 4

after shuffle
0 => 4
1 => 1
2 => 3
3 => 2
Justin Knoll
26-Feb-2004 06:37
Benton,
Thanks for the corrections. The for loop is corrected in your code, but I believe you overlooked changing my error in the call to mt_rand() ($i, not $i+1). Below is your version with that trivial change:

function fisherYatesShuffle(&$array)
{
   for ($i = 0; $i<count($array); $i++)
   {
         $j = @mt_rand(0, $i);
         $temp = $array[$i];
         $array[$i] = $array[$j];
         $array[$j] = $temp;
   }
}
Benton at GoatRider dot com
30-Jan-2004 05:05
That implementation of Fisher-Yates is all messed up. First of all, what's this?

for ($i = count($array); --$i; $i > 0)

That abuses the "for" statement, swapping the increment and the comparison fields. It just happens to work because --$i eventually hits 0.

Also, the mt_rand() should be (0, $i) not ($i+1), with $i+1 there's a 1 in N chance on the first pass it shuffles in 1 past the end of the array, putting a blank at the last element.

Here's a fixed version. I swapped it around to go from small to big:

function fisherYatesShuffle(&$array)
{
   for ($i = 0; $i<count($array); $i++)
   {
         $j = @mt_rand(0, $i+1);
         $temp = $array[$i];
         $array[$i] = $array[$j];
         $array[$j] = $temp;
   }
}
Justin Knoll
13-Nov-2003 02:57
Here's an implementation of a canonical shuffling algorithm.

Its O(n), not O(n^2). The implementation of Fisher-Yates below uses array splicing inside a for loop over the array, making it O(n^2).

It creates a uniform distribution of permutations - the definition of a shuffle. I'm not sure that all of the ad hoc algorithms below do this - they might create shuffles that look random on casual inspection, but aren't.

Many implementations of Fisher-Yates check to make sure that $i != $j before swapping. I figure that for large lists, that check incurs more cost than just swapping every time.

<?php
/**
 * Shuffles an array using the Fisher-Yates shuffle.
 *
 * D. E. Knuth: The Art of Computer Programming, Volume 2,
 * Third edition. Section 3.4.2, Algorithm P, pp 145. Reading:
 * Addison-Wesley, 1997. ISBN: 0-201-89684-2.
 *
 * R. A. Fisher and F. Yates: Statistical Tables. London, 1938.
 * Example 12.
 *
 * @author Justin Knoll
 * @param array The array to be sorted - passed by reference.
 * @return The shuffled array.
 */
function fisherYatesShuffle(&$array)
{
   for (
$i = count($array); --$i; $i > 0)
   {
        
$j = @mt_rand(0, $i+1);
      
$temp = $array[$i];
        
$array[$i] = $array[$j];
        
$array[$j] = $temp;
   }
}
?>

<rsortsizeof>
 Last updated: Thu, 19 May 2005
Copyright © 2001-2005 The PHP Group
All rights reserved.
This unofficial mirror is operated at: The Server Pages
Last updated: Thu May 19 17:35:34 2005 CDT