note 25007 added to function.shuffle

From: Date: Sat, 07 Sep 2002 17:02:57 +0000
Subject: note 25007 added to function.shuffle
Groups: php.notes 
Request: Send a blank email to php-notes+get-36306@lists.php.net to get a copy of this message
The one-liner code does not work well and is still incorrect after the proposed patch, as the first loop is executed without initializing $r: for($c = count($arr); $c > 0; $r = mt_rand(0, $c--)) array_splice($arr, $r, $c - $r, array_reverse(array_slice($arr, $r, $c - $r))); The correct way would be to use: for($c = count($arr); $c > 0; $c--) { $r = mt_rand(0, $c); array_splice($arr, $r, $c - $r, array_reverse(array_slice($arr, $r, $c - $r))); } Still, it runs too slowly, because of the many array copies and creation by the internal array_splice and array_reverse. Use it only with small arrays, as the time needed grows in O(N^2) where N is the count of element in the array... A faster approach, in O(N), does not reverse a splice, but swaps each position with a random position in the array. The following code works with indexed array (with integer keys from 0 to N-1), not with associative arrays: for($c = count($arr); $c > 0; $c--) { $r = mt_rand(0, $c); $v = $arr[$c]; $arr[$c] = $arr[$r]; $arr[$r] = $v; } To use this technic with large associative arrays, one can first shuffle a range(0, count($arr)), then use array_multisort() to sort the $arr by this shuffled range. -- http://www.php.net/manual/en/function.shuffle.php http://master.php.net/manage/user-notes.php?action=edit+25007 http://master.php.net/manage/user-notes.php?action=delete+25007 http://master.php.net/manage/user-notes.php?action=reject+25007

« previous php.notes (#36306) next »