The Server Pages
:: TSP Menu
- Home
- Authors
- Glossary
- RSS Feed

:: Servers
- CPanel
- Hosting
- Linux
- Windows

:: Webmaster
- Databases
- Design
- PHP
- Search Engines

:: Scripts
- Scripts

:: Documentation
- PHP Manual

:: Other
- Errors & Solutions
- TechPunt
- Wojjie

search for in the

sizeof> <rsort
[edit] Last updated: Sat, 12 May 2012

view this page in

shuffle

(PHP 4, PHP 5)

shuffleShuffle an array

Description

bool shuffle ( array &$array )

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

Parameters

array

The array.

Return Values

Returns TRUE on success or FALSE on failure.

Examples

Example #1 shuffle() example

<?php
$numbers 
range(120);
shuffle($numbers);
foreach (
$numbers as $number) {
    echo 
"$number ";
}
?>

Changelog

Version Description
4.2.0The random number generator is seeded automatically.

Notes

Note: This function assigns new keys to the elements in array. It will remove any existing keys that may have been assigned, rather than just reordering the keys.



sizeof> <rsort
[edit] Last updated: Sat, 12 May 2012
 
add a note add a note User Contributed Notes shuffle
tim at leethost dot com 26-Sep-2011 06:15
This is a great SEO function for web developers.  It shuffles the array, but does it identically each time. SEOshuffle guarantees shuffled yet consistent order.

<?php
/* $seed variable is optional */
function SEOshuffle(&$items, $seed=false) {
 
$original = md5(serialize($items));
 
mt_srand(crc32(($seed) ? $seed : $items[0]));
  for (
$i = count($items) - 1; $i > 0; $i--){
   
$j = @mt_rand(0, $i);
    list(
$items[$i], $items[$j]) = array($items[$j], $items[$i]);
  }
  if (
$original == md5(serialize($items))) {
    list(
$items[count($items) - 1], $items[0]) = array($items[0], $items[count($items) - 1]);
  }
}
?>
timtrinidad at gmail dot com 08-Aug-2011 12:38
It appears that the suhosin extensions >= 0.9.26 that have the suhosin.mt_srand.ignore and suhosin.srand.ignore settings set to "Off" do not affect shuffle().

In other words, the only way I was able to get pseudo-random and predictable results through shuffle() was to disable the extension.
Donald 14-Jun-2011 08:25
Very simple shuffle function preserving key with value

<?php
function shuffle_assoc( $array )
{
  
$keys = array_keys( $array );
  
shuffle( $keys );
   return
array_merge( array_flip( $keys ) , $array );
}
?>
Eric Anderson 29-Mar-2011 09:33
Copy and paste this script and refresh the page to see the shuffling effect.

<?php
   
/**
    * Shuffles and displays cards in a deck
    * @author:     Eric Anderson
    * @filename:   deckofcards.php
    */
   
    // Create an array of face values
    // and an array of card values
    // then merge them together
   
$cards = array_merge(array("J", "Q", "K", "A"), range(2,10)); // 13 cards
   
    // Shuffle the cards
   
shuffle($cards);
   
   
// Create an multidimentional array to hold the 4 suits
   
$suits = array(
       
'Heart' => array(),
       
'Spade' => array(),
       
'Diamond' => array(),
       
'Club' => array()
        );
       
   
// Add cards to their respective suits
   
for($i = 0; $i < count($suits); $i++)
    {
        for(
$j = 0; $j < count($cards); $j++)
        {
           
$suits['Heart'][$j] = $cards[$j]."<span style=color:#FF0000;>&hearts;</span>";
           
$suits['Spade'][$j] = $cards[$j]."&spades;";
           
$suits['Diamond'][$j] = $cards[$j]."<span style=color:#FF0000;>&diams;</span>";
           
$suits['Club'][$j] = $cards[$j]."&clubs;";
        }
    }
   
   
// Create a deck
   
$deck = array();
   
   
// Merge the suits into the empty deck array
   
$deck = array_merge($deck, $suits);
               
   
// Display the deck to the screen
   
echo "<p><b>Deck of cards:</b></p>";
    foreach(
$deck as $k1 => $v1)
    {
       
// Display suit name
       
echo "<p>&emsp;$k1's<br />&emsp;{<br />&emsp;&emsp;";
       
$acc = 0;
       
       
// Display card value
       
foreach($v1 as $k2 => $v2)
        {
            echo
"$v2&nbsp";
           
$acc++;
           
            if (
$acc == 4)
            {
                echo
"<br />&emsp;&emsp;";
               
$acc = 0;
            }
        }
        echo
"<br />&emsp;}</p>";
    }
?>
andjones at gmail dot com 26-Aug-2010 09:35
Shuffle associative and non-associative array while preserving key, value pairs. Also returns the shuffled array instead of shuffling it in place.

<?php

function shuffle_assoc($list) {
  if (!
is_array($list)) return $list;

 
$keys = array_keys($list);
 
shuffle($keys);
 
$random = array();
  foreach (
$keys as $key)
   
$random[$key] = $list[$key];

  return
$random;
}

?>
ezakto at ezakto dot com 24-Jul-2010 11:13
This is a replica of shuffle() but preserving keys (associative and non-associative)

bool kshuffle  (  array &$array  )

<?php

function kshuffle(&$array) {
    if(!
is_array($array) || empty($array)) {
        return
false;
    }
   
$tmp = array();
    foreach(
$array as $key => $value) {
       
$tmp[] = array('k' => $key, 'v' => $value);
    }
   
shuffle($tmp);
   
$array = array();
    foreach(
$tmp as $entry) {
       
$array[$entry['k']] = $entry['v'];
    }
    return
true;
}

$array = array('first' => 0, 'second' => 1, 'third' => 2);
kshuffle($array);
print_r($array); // [second] => 1 [first] => 0 [third] => 2

$array = array('first', 'second', 'third');
kshuffle($array);
print_r($array); // [1] => second [2] => third [0] => first

?>
m0gr14 at gmail dot com 04-Jul-2010 10:39
This function shuffles an associative array recursive.

<?php

/**
* Shuffles an associative array recursive
* @author Mogria <m0gr14@gmail.com>
* @param array $array
* @return array
*
*/

function rec_assoc_shuffle($array)
{
 
$ary_keys = array_keys($array);
 
$ary_values = array_values($array);
 
shuffle($ary_values);
  foreach(
$ary_keys as $key => $value) {
    if (
is_array($ary_values[$key]) AND $ary_values[$key] != NULL) {
     
$ary_values[$key] = rec_assoc_shuffle($ary_values[$key]);
    }
   
$new[$value] = $ary_values[$key];
  }
  return
$new;
}

?>

Example of use:
<?php
$array
=
    Array(
       
1,
        Array(
           
1,
           
2,
           
3,
           
4,
            Array(
               
1,
               
2,
               
3,
               
4,
               
5
           
)
        ),
       
2,
       
3,
        Array(
           
0,
           
1,
                Array(
                   
1,
                   
2,
                   
3,
                   
4,
                        Array(
                           
1,
                           
6,
                           
5,
                           
2,
                           
1,
                           
3
                       
)
                )
        ),
       
4,
       
5,
       
6,
       
7
   
);
$array = rec_assoc_shuffle($array);
echo
'<pre>';
print_r($array);
echo
'</pre>';

/*
Returns:
Array
(
    [0] => 6
    [1] => 5
    [2] => Array
        (
            [0] => 1
            [1] => 3
            [2] => Array
                (
                    [0] => 3
                    [1] => 1
                    [2] => 2
                    [3] => 4
                    [4] => 5
                )

            [3] => 2
            [4] => 4
        )

    [3] => 3
    [4] => Array
        (
            [0] => Array
                (
                    [0] => 3
                    [1] => 1
                    [2] => 4
                    [3] => Array
                        (
                            [0] => 5
                            [1] => 1
                            [2] => 3
                            [3] => 6
                            [4] => 1
                            [5] => 2
                        )

                    [4] => 2
                )

            [1] => 1
            [2] => 0
        )

    [5] => 2
    [6] => 1
    [7] => 4
    [8] => 7
)

*/

?>
rick at suggestive dot com 24-Mar-2010 02:19
Many people in SEO need to supply an array and shuffle the results and need the same result each time that page is generated. This is my implementation with a working example:

<?php
function seoShuffle(&$items,$string) {
   
mt_srand(strlen($string));
    for (
$i = count($items) - 1; $i > 0; $i--){
       
$j = @mt_rand(0, $i);
       
$tmp = $items[$i];
       
$items[$i] = $items[$j];
       
$items[$j] = $tmp;
    }
}

$items = array('one','two','three','four','five','six');
$string = 'whatever';

echo
'<pre>';
print_r($items);
echo
'</pre>';

seoShuffle($items,$string);

echo
'<pre>';
print_r($items);
echo
'</pre>';
?>
tyler at CompLangs dot com 01-Jan-2010 06:59
Here is a quick function I wrote that generates a random password and uses shuffle() to easily shuffle the order.

<?php
public function randPass($upper = 3, $lower = 3, $numeric = 3, $other = 2) {
   
//we need these vars to create a password string
   
$passOrder = Array();
   
$passWord = '';

   
//generate the contents of the password
   
for ($i = 0; $i < $upper; $i++) {
       
$passOrder[] = chr(rand(65, 90));
    }
    for (
$i = 0; $i < $lower; $i++) {
       
$passOrder[] = chr(rand(97, 122));
    }
    for (
$i = 0; $i < $numeric; $i++) {
       
$passOrder[] = chr(rand(48, 57));
    }
    for (
$i = 0; $i < $other; $i++) {
       
$passOrder[] = chr(rand(33, 47));
    }

   
//randomize the order of characters
   
shuffle($passOrder);

   
//concatenate into a string
   
foreach ($passOrder as $char) {
       
$passWord .= $char;
    }

   
//we're done
   
return $passWord;
}
?>
ahmad at ahmadnassri dot com 18-Nov-2009 08:58
shuffle for associative arrays, preserves key=>value pairs.
(Based on (Vladimir Kornea of typetango.com)'s function)

<?php
   
function shuffle_assoc(&$array) {
       
$keys = array_keys($array);

       
shuffle($keys);

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

       
$array = $new;

        return
true;
    }
?>

*note: as of PHP 5.2.10, array_rand's resulting array of keys is no longer shuffled, so we use array_keys + shuffle.
Anonymous 28-Aug-2009 09:18
I needed a simple function two shuffle a two dimensional array. Please note the second level arrays must be indexed using integers, for example $myarray[0]["Name"] and not $myarray["One"]["Name"]. Here is the function:

<?php
function twodshuffle($array)
{
   
// Get array length
   
$count = count($array);
   
// Create a range of indicies
   
$indi = range(0,$count-1);
   
// Randomize indicies array
   
shuffle($indi);
   
// Initialize new array
   
$newarray = array($count);
   
// Holds current index
   
$i = 0;
   
// Shuffle multidimensional array
   
foreach ($indi as $index)
    {
       
$newarray[$i] = $array[$index];
       
$i++;
    }
    return
$newarray;
}
?>

Please note it only works on two dimensional arrays. Here is an example:

<?php
$myarray
= array("Google" => array("Name" => "Google", "URL" => "www.google.com", "Usage" => "Googling"), "Yahoo" => array("Name" => "Yahoo", "URL" => "www.yahoo.com", "Usage" => "Yahooing?"), "Ask" => array("Name" => "Ask", "URL" => "www.ask.com", "Usage" => "Asking Jeeves"));

print_r(twodshuffle($myarray));

/* And the result is:
Array ( [0] => Array ( [Name] => Ask [URL] => www.ask.com [Usage] => Asking Jeeves ) [1] => Array ( [Name] => Google [URL] => www.google.com [Usage] => Googling ) [2] => Array ( [Name] => Yahoo [URL] => www.yahoo.com [Usage] => Yahooing? ) )
*/
?>

Hope you find it useful!
John Galt 21-Jul-2009 09:08
I wrote these functions just for the heck of it, but I managed to get them to work even though I'm a PHP amateur. They're just two functions for a deck of 52 cards. newDeck() creates a deck and deal() creates hands for the deck.

<?php
 
// Two basic playing card functions
 // newDeck([$numJokers]) - returns array of 52 cards plus (if supplied) $numJokers jokers
 // deal($deck[, $numHands[, $numCards]]) - returns two compact()ed variables--the new $deck and $hand arrays

 
function newDeck($numJokers = 0)
 {
 
// Returns $deck: array of 52 standard deck of 4-suit cards plus $numJokers jokers, shuffled (key starts at zero)
  // in format of e.g. $deck[4] = "A &spades;" = ace of spades (fifth card)
 
$suitCards = array("J", "Q", "K", "A");
 
$suitCards = array_merge($suitCards, range(2, 10));
 
$hearts = array();
 
$spades = array();
 
$diamonds = array();
 
$clubs = array();
  foreach(
$suitCards as $card)
  {
  
$hearts[] = "<span style=\"color: #FF0000;\">" . $card . " &hearts;" . "</span>";
  
$spades[] = "<span style=\"color: #000000;\">" . $card . " &spades;" . "</span>";
  
$diamonds[] = "<span style=\"color: #FF0000;\">" . $card . " &diams;" . "</span>";
  
$clubs[] = "<span style=\"color: #000000;\">" . $card . " &clubs;" . "</span>";
  }
 
$jokers = array();
  for(
$i = 0; $i < $numJokers; $i++)
  
$jokers[] = "<span style=\"color: #8467D7;\">JOKER</span>";
 
$deck = array_merge($hearts, $spades, $clubs, $diamonds, $jokers);
 
shuffle($deck);
  return
$deck;
 }

 function
deal($deck, $numHands = 1, $numCards = 7)
 {
 
// Returns $hand: two-dimensional array, first key being player ID and second being card number (both starting from zero)
  // e.g. $hand[2][4] = "6 &hearts;" = six of hearts (third hand, fifth card)
  // To return, use extract, e.g. extract(deal($deck, 2, 13)); (also returns $deck)
 
$hand = array();
  for(
$i = 0; $i < $numHands; $i++)
  {
   for(
$j = 0; $j < $numCards; $j++)
   {
   
$hand[$i][$j] = next($deck);
    if(
$i == 0 && $j == 0)
    
$hand[0][0] = prev($deck);
   }
  }
 
$deck = array_splice($deck, ($numHands * $numCards));
  return
compact("hand", "deck");
 }

 
$deck = newDeck();
 
extract(deal($deck, 3, 7));

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <!-- Just an example of test output to demonstrate capability. -->
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Basic Playing Card Functions</title>
 </head>

 <body>
  <h1>Deck</h1>
  <pre>
<?php
 print_r
($deck);
?>
  </pre>
  <hr />
  <h1>Hands</h1>
  <pre>
<?php
 print_r
($hand);
?>
  </pre>
 </body>
</html>
mateusz dot charytoniuk at gmail dot com 20-Jun-2009 12:19
If you want to keep array shuffled in one particular way for every user visiting your site, you can use:

<?php
srand
($user['id']);
shuffle($some_array);
?>
aalaap at gmail dot com 08-Jun-2009 05:12
I've been wondering why shuffle() doesn't provide the shuffled array as a return value instead of a bool. I mean, what could possibly go wrong in shuffling elements from an array?

So I use something like this:

<?php
function array_shuffle($array) {
    if (
shuffle($array)) {
        return
$array;
    } else {
        return
FALSE;
    }
}
?>
sivaji2009 at gmail dot com 17-May-2009 02:07
Here i wrote a custom shuffle function which preserves the array index and distributes the array element randomly.

<?php

/*
 * return an array whose elements are shuffled in random order.
 */
function custom_shuffle($my_array = array()) {
 
$copy = array();
  while (
count($my_array)) {
   
// takes a rand array elements by its key
   
$element = array_rand($my_array);
   
// assign the array and its value to an another array
   
$copy[$element] = $my_array[$element];
   
//delete the element from source array
   
unset($my_array[$element]);
  }
  return
$copy;
}

$array = array(
 
'a' => 'apple',
 
'b' => 'ball',
 
'c' => 'cat',
 
'd' => 'dog',
 
'e' => 'egg',
 
'f' => 'fan',
 
'g' => 'gun'
);

print_r(custom_shuffle($array));

Array
(
    [
c] => cat
   
[e] => egg
   
[f] => fan
   
[a] => apple
   
[b] => ball
   
[g] => gun
   
[d] => dog
)

?>
dirk dot avery a t gmail 30-Apr-2009 08:58
Building on examples by m227 and pineappleclock, here is a function that returns all permutations of each set in the power set of an array of strings (instead of a string).  Thanks for the great examples!

<?php

/*
 Use: $arr = power_perms($in);

 Example:
  $in = array("A","B","C");
  $power_perms = power_perms($in);
 
 Returns:
  Array
  (
    [0] => Array
        (
            [0] => A
            [1] => B
            [2] => C
        )

    [1] => Array
        (
            [0] => A
            [1] => C
            [2] => B
        )

    [2] => Array
        (
            [0] => B
            [1] => A
            [2] => C
        )

    [3] => Array
        (
            [0] => B
            [1] => C
            [2] => A
        )

    [4] => Array
        (
            [0] => C
            [1] => A
            [2] => B
        )

    [5] => Array
        (
            [0] => C
            [1] => B
            [2] => A
        )

    [6] => Array
        (
            [0] => A
            [1] => B
        )

    [7] => Array
        (
            [0] => B
            [1] => A
        )

    [8] => Array
        (
            [0] => B
            [1] => C
        )

    [9] => Array
        (
            [0] => C
            [1] => B
        )

    [10] => Array
        (
            [0] => A
            [1] => C
        )

    [11] => Array
        (
            [0] => C
            [1] => A
        )

    [12] => Array
        (
            [0] => A
        )

    [13] => Array
        (
            [0] => B
        )

    [14] => Array
        (
            [0] => C
        )

  )

*/

function power_perms($arr) {

   
$power_set = power_set($arr);
   
$result = array();
    foreach(
$power_set as $set) {
       
$perms = perms($set);
       
$result = array_merge($result,$perms);
    }
    return
$result;
}

function
power_set($in,$minLength = 1) {

  
$count = count($in);
  
$members = pow(2,$count);
  
$return = array();
   for (
$i = 0; $i < $members; $i++) {
     
$b = sprintf("%0".$count."b",$i);
     
$out = array();
      for (
$j = 0; $j < $count; $j++) {
         if (
$b{$j} == '1') $out[] = $in[$j];
      }
      if (
count($out) >= $minLength) {
        
$return[] = $out;
      }
   }

  
//usort($return,"cmp");  //can sort here by length
  
return $return;
}

function
factorial($int){
   if(
$int < 2) {
       return
1;
   }

   for(
$f = 2; $int-1 > 1; $f *= $int--);

   return
$f;
}

function
perm($arr, $nth = null) {

    if (
$nth === null) {
        return
perms($arr);
    }

   
$result = array();
   
$length = count($arr);

    while (
$length--) {
       
$f = factorial($length);
       
$p = floor($nth / $f);
       
$result[] = $arr[$p];
       
array_delete_by_key($arr, $p);
       
$nth -= $p * $f;
    }

   
$result = array_merge($result,$arr);
    return
$result;
}

function
perms($arr) {
   
$p = array();
    for (
$i=0; $i < factorial(count($arr)); $i++) {
       
$p[] = perm($arr, $i);
    }
    return
$p;
}

function
array_delete_by_key(&$array, $delete_key, $use_old_keys = FALSE) {

    unset(
$array[$delete_key]);

    if(!
$use_old_keys) {
       
$array = array_values($array);
    }

    return
TRUE;
}
?>
john 18-Feb-2009 09:21
To shuffle keeping the keys intact, I've used the following:

<?PHP

$shuff
=array("a","b","c","d","e","f","g",
                  
"h","i","j","k","l");
uasort( $shuff, 'scmp' );
print_r($shuff);

function
scmp( $a, $b ) {
     return
rand(-1,1);
}

?>

Example output:
Array
(
    [7] => h
    [6] => g
    [2] => c
    [0] => a
    [5] => f
    [4] => e
    [10] => k
    [3] => d
    [8] => i
    [11] => l
    [1] => b
    [9] => j
)

Array
(
    [6] => g
    [0] => a
    [2] => c
    [10] => k
    [8] => i
    [5] => f
    [1] => b
    [4] => e
    [9] => j
    [3] => d
    [7] => h
    [11] => l
)

Works for me...
pineappleclock at gmail dot com 22-Jan-2009 10:06
If you want the Power Set (set of all unique subsets) of an array instead of permutations, you can use this simple algorithm:

<?php
/**
* Returns the power set of a one dimensional array,
* a 2-D array.
* array(a,b,c) ->
* array(array(a),array(b),array(c),array(a,b),array(b,c),array(a,b,c))
*/
function powerSet($in,$minLength = 1) {
  
$count = count($in);
  
$members = pow(2,$count);
  
$return = array();
   for (
$i = 0; $i < $members; $i++) {
     
$b = sprintf("%0".$count."b",$i);
     
$out = array();
      for (
$j = 0; $j < $count; $j++) {
         if (
$b{$j} == '1') $out[] = $in[$j];
      }
      if (
count($out) >= $minLength) {
        
$return[] = $out;
      }
   }
   return
$return;
}
?>
csaba at alum dot mit dot edu 03-Jan-2009 08:01
The following function, NKnext(), generates combinations sequentially.  NKnext's output is a string of 0s and 1s where a "1" at position k represents the kth item being selected.  For example, "1001000" represents the 0th and 3rd items being chosen from among 7.  Feed NKnext() such a string to generate the next one in the sequence.  Note that the sequence is a Gray Code where all adjacent element pairs (including the first and last) differ by a minimal amount (ie. a 0-1 swap), so that one could easily make it circular (Hamiltonian).

<?php
$n
= 7;
$k = 3;
enumNK ($n, $k);            // show all possibilities

function enumNK ($n, $k) {
 
// Iteratively generate all strings of $k "1"s and $n-$k "0"s
  // so that adjacent strings have exactly one 0-1 swap.
  // Final string is a BRR of the original (right barrel rotation)
 
print                     // print the initial string
   
$str = str_repeat("1", $k) . str_repeat("0", $n-$k);
  while (
$str= NKnext($str)) print "<br> $str"; }

function
swap ($str, $pos1, $pos2) {
 
// Return $str with characters at $pos1 and $pos2 swapped
 
$chr = $str[$pos1];
 
$str[$pos1] = $str[$pos2];
 
$str[$pos2] = $chr;
  return
$str; }

function
mod($num, $base) {    // Mathematician's modulus
  // compare with http://php.net/fmod
 
return ($num - $base*floor($num/$base)); }

function
NKnext ($str, $pos=0, $dir=1) {
 
// Assumes there were initially $k=substr_count($str, "1") contiguous 1s
  //   starting at ($dir==1=>leftmost; $dir==1=>rightmost) position $pos
  //   to be barrel rotated in the direction $dir (1=>right, -1=>left)
  //   while going through all possibilities of [$n=strlen($str), $k]
  // Returns the resultant next string in the iteration
  //   by finding the position of the next swap ($pos and $pos2)
 
NKswap ($str, $pos, $dir, substr_count ($str, "1"), strlen($str), $pos2);
  if (
$pos==$pos2) return ""; return swap($str, $pos, $pos2); }

function
NKswap ($str, &$pos, $dir, $k, $n, &$pos2) {
 
// Under the assumptions for NKnext, returns the two
  //   positions ($pos, $pos2) that are to be swapped.
  // $pos2 is set to $pos if $str is final (ie. no more swaps)
 
if (!$k || $k==$n) return $pos2 = $pos;          // all 0s or all 1s

 
$ch1 = ($str[$pos]!="0");      // Is char of interest (fixed char) a "1"?
 
$sub = substr($str, 0, $pos) . substr($str, $pos + 1);  // Rest of string

  // Position of next char of interest
 
$np = mod($pos - ($dir==1) + $ch1 * $dir * ($k-1), $n-1);

 
NKswap($sub, $np, $ch1 ? -$dir : $dir, $k---$ch1, $n-1, $pos2);
  if (
$np==$pos2)                 // If substring is done
   
return ($pos2 = mod($pos + $ch1 * $dir * ($k - !$k), $n));

  if (
$pos2>=$pos) ++$pos2;     // Adjustment for 'char of interest' posn
 
$pos = $np + ($np>=$pos); }   // Return the "normal" swap position
?>

BR = Barrel rotation
BRR/BRL = Barrel rotation to the right/left by 1

The basic algorithm is recursive, with a fixed "1" position identified ($pos=0, below), all sub-possibilities are iterated, then it is replaced with a 0, and then all those sub-possibilities are iterated.
[5, 3] example with leftmost 1 fixed: 11100 -> 10101 -> 10110 -> 11010 -> 10011 -> 11001
[5, 3] continued with leftmost char swap: 11001 -> 01101
[5, 3] continued with leftmost 0 fixed: 01101 -> 00111 -> 01011 -> 01110

When $dir is 1 in the above functions, it represents a net BRR, and $pos represents the starting position of the leftmost 1.
When $dir is -1 in the above functions, it represents a net BRL, and $pos represents the starting position of the rightmost 1.
$pos is essentially used to determine when all the swaps are done.  For example, in rotating 1110 (with $dir=1 and $pos=0) we go through the following: 1101 (and not 0111!), 1011, 0111

Happy New Year,
Csaba Gabor from Vienna
tony at brokerbin dot com 11-Nov-2008 07:26
Here is IMO the simplest and extremely fast way to shuffle an associative array AND keep the key=>value relationship.  However, it ONLY works if there are NO NUMERIC keys AT ALL.  Look into array_merge for the reason why.

<?php

$unshuffled
= array('one'=>1,'two'=>2,'three'=>3);

$shuffled = array_merge( array_flip(array_rand($unshuffled,count($unshuffled))),$unshuffled );

?>

peace
Antonio Ognio 06-May-2008 09:42
Another shuffle() implementation that preserves keys, does not use extra memory and perhaps is a bit easier to grasp.

<?php
if (function_exists('shuffle_with_keys')===false) {
  function
shuffle_with_keys(&$array) {
   
/* Auxiliary array to hold the new order */
   
$aux = array();
   
/* We work with an array of the keys */
   
$keys = array_keys($array);
   
/* We shuffle the keys */
   
shuffle($keys);
   
/* We iterate thru' the new order of the keys */
   
foreach($keys as $key) {
     
/* We insert the key, value pair in its new order */
     
$aux[$key] = $array[$key];
     
/* We remove the element from the old array to save memory */
     
unset($array[$key]);
    }
   
/* The auxiliary array with the new order overwrites the old variable */
   
$array = $aux;
  }
}
?>
rich at home dot nl 23-Jan-2008 09:17
Function that does the same as shuffle(), but preserves key=>values.
(Based on (Vladimir Kornea of typetango.com)'s function)

<?php
 
function shuffle_assoc(&$array) {
    if (
count($array)>1) { //$keys needs to be an array, no need to shuffle 1 item anyway
     
$keys = array_rand($array, count($array));

      foreach(
$keys as $key)
       
$new[$key] = $array[$key];

     
$array = $new;
    }
    return
true; //because it's a wannabe shuffle(), which returns true
 
}

 
$test = array(1=>'one','two'=>'2',3=>'3');
 
print_r($test);
 
shuffle_assoc($test);
 
print_r($test);

?>

Array
(
    [1] => one
    [two] => 2
    [3] => 3
)
Array
(
    [two] => 2
    [1] => one
    [3] => 3
)
carrox at mail dot ru 23-Dec-2007 02:15
Very fast way to shuffle associative array and keep key=>value

<?php

  $tmp
=array("one"=>1,"two"=>2,"three"=>3,"four"=>4);
 
$new=array();
 
$c=count($tmp);

 
$k=array_keys($tmp);
 
$v=array_values($tmp);

   while(
$c>0) {
    
$i=array_rand($k);
    
$new[$k[$i]]=$v[$i];
     unset(
$k[$i]); #exlude selected number from list
    
$c--;
   }

  
print_r($tmp);
  
print_r($new);

?>


Result:

Array
(
    [one] => 1
    [two] => 2
    [three] => 3
    [four] => 4
)
Array
(
    [two] => 2
    [three] => 3
    [four] => 4
    [one] => 1
)

And thats all, folks!
downforme at gmx dot at 06-Nov-2007 10:08
my approach to bring some chaos to associative arrays
<?php
define
("SHUFFLEBOTH", 0);
define ("SHUFFLEVALUES", 1);
define ("SHUFFLEKEYS", 2);
function
shuffle_assoc(&$array, $mode=SHUFFLEBOTH) {
   
$keys = array_keys($array);
   
$values = array_values($array);
    if ((
$mode==SHUFFLEBOTH) || ($mode==SHUFFLEVALUES)) shuffle($values);
    if ((
$mode==SHUFFLEBOTH) || ($mode==SHUFFLEKEYS)) shuffle($keys);
   
$array = array_combine($keys, $values);
}
?>
hauser dot j at gmail dot com 14-Feb-2007 02:19
Permutation using recursion

<?php
function perm($n)
{
    if(
$n <= 1) return 1;
    else return
$n * perm($n-1);
}
?>

Usage example:
<?php $result = perm(8); ?>

$result will be 40320
m227 at tlen dot pl 13-Oct-2006 03:22
here come my three pennies about permutations. I did function below to work with word anagrams, it works flawlessly, however may be seen as a slow one.

<?php
/** (c) on LGPL license 2006.10 michal@glebowski.pl */
function fact($int){
   if(
$int<2)return 1;
   for(
$f=2;$int-1>1;$f*=$int--);
   return
$f;
}

/** @return string string $s with $n-th character cut */
function del($s, $n) {
    return
substr($s, 0, $n).substr($s, $n+1);
}
/**
 * @param $s string word to permute
 * @param $n int n-th permutation 
 * @return string n-th permutation (out of strlen(string)!)
 */ 
function perm($s, $n = null) {

    if (
$n === null) return perms($s);

   
$r = '';
   
$l = strlen($s);
    while (
$l--) {
       
$f = fact($l);
       
$p = floor($n/$f);
       
$r.= $s{$p};
       
$s = del($s, $p);
       
$n-= $p*$f;
    }
   
$r.=$s;
    return
$r;
}
/** @return array array of all permutations */
function perms($s) {
   
$p = array();
    for (
$i=0;$i<fact(strlen($s));$i++)    $p[] = perm($s, $i);
    return
$p;
}
?>
07-Jun-2006 02:53
Posted below is code that you would expect to work

<?php

$keys
= shuffle(array_keys($arr));

foreach (
$keys as $key) {

 
$arr_elem = $arr[$key];
 
// do what you want with the array element

}

?>

This in fact does not work because shuffle returns a boolean true or false. More accurate code using this method would be:

<?php

$keys
= array_keys($arr);
shuffle($keys);

foreach (
$keys as $key) {

 
$arr_elem = $arr[$key];
 
// do what you want with the array element

}

?>
alejandro dot garza at itesm dot mx 10-Mar-2006 08:47
This is taken from an O'Reilly Book and modified slightly to return all possible permutations of a 1D array:

<?php

# Modified from http://linuxalpha1.eicn.ch/OReilly_books/books/webprog/pcook/ch04_26.htm
# Takes a non-associatuve 1D (vector) array of items
#  and returns an array of arrays with each possible permutation
function array_2D_permute($items, $perms = array( )) {
static
$permuted_array;
    if (empty(
$items)) {
       
$permuted_array[]=$perms;
       
#print_r($new);
      #print join(' ', $perms) . "\n";
   
}  else {
        for (
$i = count($items) - 1; $i >= 0; --$i) {
            
$newitems = $items;
            
$newperms = $perms;
             list(
$foo) = array_splice($newitems, $i, 1);
            
array_unshift($newperms, $foo);
            
array_2D_permute($newitems, $newperms);
         }
         return
$permuted_array;
    }
}

$arr=array("Architecture","Mexico","Periodicals","Test");
$result=array_2D_permute($arr);
print_r($result);
?>
bill at SWScripts dot com 22-Sep-2005 09:45
Just a quick note to let people know that shuffle() will work on multidimensional associative arrays provided that the first key is already numeric.

So this array can be shuffled without losing any of the secondary keys or their values:

$array[0]['color'], $array[0]['size'], $array[0]['fabric']
. . .
$array[50]['color'], $array[50]['size'], $array[50]['fabric']

I recently ran up against needing to randomize this array and tried shuffle even though it's not really for associative arrays.

Hope it helps somebody out there.
Markus of CodeWallah.Com 30-Aug-2005 10:55
Here's a pretty little function to shuffle an associative array, taking a bit different approach from the earlier entries.

<?PHP
function ass_array_shuffle ($array) {
    while (
count($array) > 0) {
       
$val = array_rand($array);
       
$new_arr[$val] = $array[$val];
        unset(
$array[$val]);
    }
    return
$new_arr;
}
?>

In the function above, the original array is randomly scavenged upon until nothing is left of it. This removes the need for any temporary variables, or indeed for any superfluous tossing around of stuff.
skissane at iips dot mq dot edu dot au 06-Jun-2005 03:11
note that in PHP 5.0.4 (and assumably earlier versions as well), shuffle internally calls rand(), not mt_rand().

This was important because I was trying to use a fixed seed to get repeatable results, by calling mt_srand(). But of course that doesn't work, since shuffle uses rand() not mt_rand(). The solution is either to use srand() for seeding, or to write your own version of shuffle() using mt_rand(). (See examples which others have contributed; or, just have a look at ext/standard/array.c) mt_rand on many platforms gives better results than the builtin library anyway...

N.B. Obviously, the way the shuffle function is implemented may change without notice in future versions, including e.g. changing to use mt_rand instead.
monte at ohrt dot com 21-Mar-2005 02:10
[EDIT by danbrown AT php DOT net: As pointed out on 25 July, 2008, by "Anonymous", this implementation may have some errors or inconsistencies that may cause this function not to achieve the desired result.  "Anonymous" provided the following link for more information: http://en.wikipedia.org/wiki/Fisher-Yates_shuffle]

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.)

<?php
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;
   }
}
?>
Bjorn AT smokingmedia DOT com 23-Sep-2004 05: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
)

*/
?>
Justin Knoll 15-Apr-2004 05: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 07: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

 
show source | credits | sitemap | contact | advertising | mirror sites