shuffle
(PHP 4, PHP 5, PHP 7, PHP 8)
shuffle — 配列をシャッフルする
説明
この関数は、配列をシャッフル (要素の順番をランダムに) します。
警告
この関数が生成する値は、暗号学的にセキュアではありません。そのため、これを暗号や、戻り値を推測できないことが必須の値として使っては いけません。
暗号学的にセキュアな乱数が必要な場合は、Random\Randomizer を Random\Engine\Secure と一緒に使いましょう。簡単なユースケースの場合、random_int() と random_bytes() 関数が、オペレーティングシステムの CSPRNG を使った、 便利で安全な API を提供します。
パラメータ
array
-
配列。
戻り値
常に true
を返します。
例
例1 shuffle() の例
<?php
$numbers = range(1, 20);
shuffle($numbers);
foreach ($numbers as $number) {
echo "$number ";
}
?>
注意
注意: この関数は、
array
パラメータの要素に対して新しいキーを割り当てます。 その際、単純にキーを並べ替える代わりに、 すでに割り当てられている既存のキーを削除してしまいます。
注意:
この関数をコールすると、配列の内部ポインタは最初の要素にリセットされます。
参考
- Random\Randomizer::shuffleArray() - 配列の順列を取得する
- Random\Randomizer::shuffleBytes() - 指定された文字列の、バイト単位の順列を取得する
- Random\Randomizer::pickArrayKeys() - ランダムに配列のキーを選択する
- 配列ソート関数の比較
+add a note
User Contributed Notes 16 notes
ahmad at ahmadnassri dot com ¶
15 years ago
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.
andjones at gmail dot com ¶
14 years ago
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;
}
?>
Anonymous ¶
15 years ago
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!
dirk dot avery a t gmail ¶
15 years ago
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;
}
?>
pineappleclock at gmail dot com ¶
15 years ago
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;
}
?>
peter at removethisplease dot ddcrew dot com ¶
11 years ago
This seems to do reasonably well as a shuffle() that preserves index assocation:
<?php
function ashuffle (&$arr) {
uasort($arr, function ($a, $b) {
return rand(-1, 1);
});
}
?>
Obviously only works if PHP has closures enabled...
xzero at elite7hackers dot net ¶
9 years ago
There is an function which uses native shuffle() but preserves keys, and their order, so at end, only values are shuffled.
<?PHP
/**
* Array Quake - Give an array good quake so every value will endup with random given space.
* Keys, and their order are preserved.
* @author xZero <xzero@elite7hackers.net>
* @param array $array
* @return boolean false on failure
*/
function array_quake(&$array) {
if (is_array($array)) {
$keys = array_keys($array); // We need this to preserve keys
$temp = $array;
$array = NULL;
shuffle($temp); // Array shuffle
foreach ($temp as $k => $item) {
$array[$keys[$k]] = $item;
}
return;
}
return false;
}
// Example
$numbers = array(
'ZERO' => 0,
'ONE' => 1,
'TWO' => 2,
'THREE' => 3,
'FOUR' => 4,
'FIVE' => 5,
'SIX' => 6,
'SEVEN' => 7,
'EIGHT' => 8,
'NINE' => 9
);
echo "\nBefore (original):\n";
print_r($numbers);
array_quake($numbers);
echo "\n\nAfter (Array Quake);\n";
print_r($numbers);
echo "\n";
?>
Result example:
Before (original):
Array
(
[ZERO] => 0
[ONE] => 1
[TWO] => 2
[THREE] => 3
[FOUR] => 4
[FIVE] => 5
[SIX] => 6
[SEVEN] => 7
[EIGHT] => 8
[NINE] => 9
)
After (Array Quake);
Array
(
[ZERO] => 4
[ONE] => 2
[TWO] => 0
[THREE] => 8
[FOUR] => 3
[FIVE] => 6
[SIX] => 1
[SEVEN] => 7
[EIGHT] => 5
[NINE] => 9
)
tony at brokerbin dot com ¶
16 years ago
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
aalaap at gmail dot com ¶
15 years ago
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;
}
}
?>
ezakto at ezakto dot com ¶
14 years ago
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
?>
rick at suggestive dot com ¶
14 years ago
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>';
?>
sivaji2009 at gmail dot com ¶
15 years ago
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
)
?>
Eric Anderson ¶
13 years ago
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;>♥</span>";
$suits['Spade'][$j] = $cards[$j]."♠";
$suits['Diamond'][$j] = $cards[$j]."<span style=color:#FF0000;>♦</span>";
$suits['Club'][$j] = $cards[$j]."♣";
}
}
// 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> $k1's<br /> {<br />  ";
$acc = 0;
// Display card value
foreach($v1 as $k2 => $v2)
{
echo "$v2 ";
$acc++;
if ($acc == 4)
{
echo "<br />  ";
$acc = 0;
}
}
echo "<br /> }</p>";
}
?>
tyler at CompLangs dot com ¶
14 years ago
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;
}
?>
Antonio Ognio ¶
16 years ago
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;
}
}
?>
DiosDe ¶
3 years ago
implementation of shuffle() using random_int()
<?php
function random_int_shuffle ( array $array ): array
{
$array = array_values($array);
$result = [];
$skip_indexes = [];
$sizeof_array = count($array);
for ( $i = 0; $i < $sizeof_array; $i++ )
{
do
{
$random_index = random_int(0, $sizeof_array);
} while ( in_array($random_index, $skip_indexes) );
$skip_indexes[] = $random_index;
$result[] = $array[$random_index];
}
return $result;
}
?>