Shuffle An Array In PHP

24th January 2008

To randomise an array in PHP use the shuffle() function like this.

  1. $array = range(1,5);
  2. shuffle($array); // randomise array

There are two limitations to this function. The first is that it completely removes any key association that you may have set up. So the following array.

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

Would be turned into the following after using shuffle().

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

A way around this is to use the following function, this uses the PHP function array_rand() to extract the all of the keys in the array in a random order before ensuring that the key associations are in place.

  1. function shuffle_me($shuffle_me){
  2. $randomized_keys = array_rand($shuffle_me, count($shuffle_me));
  3. foreach($randomized_keys as $current_key) {
  4. $shuffled_me[$current_key] = $shuffle_me[$current_key];
  5. }
  6. return $shuffled_me;
  7. }

The second limitation to the shuffle() function is the degree of randomness that is created. In order to give a rough estimate of how random a randomising function is you can use the following code.

  1. $rangeStart = 1;
  2. $rangeEnd = 2;
  3. $loops = 100000;
  4. $results = array();
  5. for($i=0;$i'.print_r($tmp,true).'
'; $start = current($tmp); // get first item $end = end($tmp); // get last item echo '

Start: '.$start.' End: '.$end.' Difference: '.($start-$end).'

';

This code runs a loop 100,000 times, each time it creates a small array containing the values 1 and 2, randomises it and then stores the result as a string of numbers in another array. After the loop the PHP function array_count_values() is used to count the number of times that each value has been created and then looks to see the difference between the the lowest occurring value and the highest occurring value. The greater the number the more random the randomising function is. This shouldn't be used as the absolute truth because there are more factors at work with randomising arrays, but it gives a nice approximation.

To get a good level of randomness with a array randomising function you should use the Fisher-Yates shuffle. Here is an example of a function that uses this algorithm.

  1. function array_shuffle($array){
  2. // shuffle using Fisher-Yates
  3. $i = count($array);
  4.  
  5. while(--$i){
  6. $j = mt_rand(0,$i);
  7. if($i != $j){
  8. // swap items
  9. $tmp = $array[$j];
  10. $array[$j] = $array[$i];
  11. $array[$i] = $tmp;
  12. }
  13. }
  14. return $array;
  15. }

Using the previously mentioned random testing code it was found that the native PHP shuffle() function gave an average difference of 27, whereas the Fisher-Yates shuffle gave an average difference of 273.

So if randomness is very important to you then you probably shouldn't use the shuffle() function.

Comments

Permalink
heyy thanks for the article. very useful. the shuffle wasn't giving me very good randomization.

venksster (Mon, 12/07/2009 - 08:46)

Permalink
Hi, I found your page with this php array searching with Google. I am writing you to see if you can help me. I have one (1) topsite list with banners rotating at the center, left and right. The problem is that I'm developing a second topsite with the same structure, same code, same array, but I cannot get rotate banners, there is no way to make them rotate. The array I am using is very similar to yours: //randomly shuffle the array keeping the relation between keys and values 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; } $center_banners=shuffle_me($center_banners); $center_banners=array_slice($center_banners, 0, 20); $left_banners=shuffle_me($left_banners); $right_banners=shuffle_me($right_banners); ?> Could you help me? I am really very little expertise in this area, I do not understand why the script works perfectly in one topsite and in another topsite, which is a clone of the first one, does not work. What determines that the banners rotate in addition to the script? Thanks for your help Marlon

Marlon Soto (Thu, 02/03/2011 - 14:39)

Add new comment

The content of this field is kept private and will not be shown publicly.