PHP Conference Japan 2024

shuffle

(PHP 4, PHP 5, PHP 7, PHP 8)

shuffle將陣列洗牌

說明

shuffle(陣列 &$array): true

此函式會將一個陣列洗牌(隨機排列元素的順序)。

注意

此函式不會產生密碼學安全的數值,而且*不得*用於密碼學用途,或需要傳回值不可預測的用途。

如果需要密碼學安全的隨機性,可以使用 Random\Randomizer 搭配 Random\Engine\Secure 引擎。對於簡單的使用案例,random_int()random_bytes() 函式提供了一個方便且安全的 API,其底層由作業系統的 CSPRNG 支援。

參數

陣列 (array)

要被洗牌的陣列。

回傳值

永遠回傳 true

更新日誌

版本 說明
7.1.0 內部的隨機化演算法已變更,使用 » 梅森旋轉演算法 亂數產生器取代 libc rand 函式。

範例

範例 #1 shuffle() 範例

<?php
$numbers
= range(1, 20);
shuffle($numbers);
foreach (
$numbers as $number) {
echo
"$number ";
}
?>

注意事項

注意這個函式會將新的鍵值指派給 array 中的元素。它會移除任何可能已指派的現有鍵值,而不是僅重新排序鍵值。

注意:

會將陣列的內部指標重設為第一個元素。

參見

新增註解

使用者貢獻的註解 16 則註解

ahmad at ahmadnassri dot com
15 年前
適用於關聯式陣列的 shuffle,保留鍵值對。
(基於 typetango.com 的 Vladimir Kornea 的函式)

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

shuffle($keys);

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

$array = $new;

return
true;
}
?>
*備註:從 PHP 5.2.10 開始,array_rand 返回的鍵值陣列不再是隨機排序的,所以我們使用 array_keys + shuffle。
andjones at gmail dot com
14 年前
在保持鍵值對的同時,隨機排序關聯式和非關聯式陣列。同時返回已隨機排序的陣列,而不是就地排序。

<?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;
}

?>
匿名
15 年前
我需要一個簡單的函式來隨機排序二維陣列。請注意,第二層的陣列必須使用整數索引,例如 $myarray[0]["Name"] 而不是 $myarray["One"]["Name"]。以下是該函式:

<?php
function twodshuffle($array)
{
// 取得陣列長度
$count = count($array);
// 建立索引範圍
$indi = range(0,$count-1);
// 隨機排序索引陣列
shuffle($indi);
// 初始化新陣列
$newarray = array($count);
// 保存目前索引
$i = 0;
// 隨機排序多維陣列
foreach ($indi as $index)
{
$newarray[$i] = $array[$index];
$i++;
}
return
$newarray;
}
?>
請注意,它只適用於二維陣列。以下是一個例子:

<?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));

/* 然後結果是:
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? ) )
*/
?>

希望對您有所幫助!
dirk dot avery a t gmail
15 年前
基於 m227 和 pineappleclock 的範例,這裡有一個函式,它返回字串陣列(而不是字串)的冪集中每個集合的所有排列。感謝這些很棒的範例!

<?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 年前
如果您想要陣列的冪集(所有唯一子集的集合)而不是排列,您可以使用這個簡單的演算法

<?php
/**
* 傳回一維陣列的冪集,
* 一個二維陣列。
* 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 年前
這似乎是一個相當不錯的 shuffle() 函式,可以保留索引關聯。

<?php
function ashuffle (&$arr) {
uasort($arr, function ($a, $b) {
return
rand(-1, 1);
});
}
?>

顯然只有在 PHP 啟用閉包的情況下才能運作...
xzero at elite7hackers dot net
9 年前
有一個函式使用原生的 shuffle() 但保留鍵值及其順序,因此最後只有值會被洗牌。

<?PHP
/**
* 陣列震盪 - 將陣列中的每個值重新排列到隨機位置。
* 鍵值及其順序將被保留。
* @author xZero <xzero@elite7hackers.net>
* @param array $array
* @return boolean 失敗時返回 false
*/
function array_quake(&$array) {
if (
is_array($array)) {
$keys = array_keys($array); // 我們需要這個來保留鍵值
$temp = $array;
$array = NULL;
shuffle($temp); // 陣列洗牌
foreach ($temp as $k => $item) {
$array[$keys[$k]] = $item;
}
return;
}
return
false;
}

// 範例
$numbers = array(
'ZERO' => 0,
'ONE' => 1,
'TWO' => 2,
'THREE' => 3,
'FOUR' => 4,
'FIVE' => 5,
'SIX' => 6,
'SEVEN' => 7,
'EIGHT' => 8,
'NINE' => 9
);
echo
"\n原始陣列 (之前):\n";
print_r($numbers);
array_quake($numbers);
echo
"\n\n震盪後的陣列 (之後):\n";
print_r($numbers);
echo
"\n";
?>

範例結果
原始陣列 (之前)
陣列
(
[ZERO] => 0
[ONE] => 1
[TWO] => 2
[THREE] => 3
[FOUR] => 4
[FIVE] => 5
[SIX] => 6
[SEVEN] => 7
[EIGHT] => 8
[NINE] => 9
)

震盪後的陣列 (之後)
陣列
(
[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 年前
這是我認為最簡單且極快速的方法來洗牌關聯式陣列並保持鍵值對應關係。 然而,它只在「完全沒有」數值鍵的情況下才有效。 詳見 array_merge 說明以了解原因。

<?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 年前
我一直很納悶,為什麼 shuffle() 不直接回傳已洗牌的陣列,而是回傳一個布林值。我的意思是,洗牌一個陣列的元素到底會出什麼錯?

所以我用了像這樣的程式碼:

<?php
function array_shuffle($array) {
if (
shuffle($array)) {
return
$array;
} else {
return
FALSE;
}
}
?>
ezakto at ezakto dot com
14 年前
這是 shuffle() 的一個複製品,但會保留鍵值(關聯式和非關聯式陣列)。

bool kshuffle ( array &$array ) (布林值 kshuffle ( 陣列 &$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 年前
許多 SEO 從業人員需要提供一個陣列並打亂結果,且每次產生頁面時都需要相同的結果。這是我的實作範例,附帶一個可運作的例子。

<?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 年前
我在這裡寫了一個自定義的洗牌函式,它可以保留陣列索引並隨機分佈陣列元素。

<?php

/*
* 返回一個元素順序已被打亂的陣列。
*/
function custom_shuffle($my_array = array()) {
$copy = array();
while (
count($my_array)) {
// 透過鍵值隨機取陣列元素
$element = array_rand($my_array);
// 將陣列元素及其值賦值給另一個陣列
$copy[$element] = $my_array[$element];
// 從來源陣列中刪除該元素
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));

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

?>
Eric Anderson
13 年前
複製並貼上此程式碼,然後重新整理頁面以查看洗牌效果。

<?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>";
}
?>
tyler at CompLangs dot com
14 年前
這是我寫的一個快速函式,它會產生一個隨機密碼,並使用 shuffle() 來輕鬆打亂順序。

<?php
public function randPass($upper = 3, $lower = 3, $numeric = 3, $other = 2) {
//我們需要這些變數來建立密碼字串
$passOrder = Array();
$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));
}

//將字元的順序隨機化
shuffle($passOrder);

//連接成字串
foreach ($passOrder as $char) {
$passWord .= $char;
}

//完成
return $passWord;
}
?>
Antonio Ognio
16 年前
另一種 shuffle() 的實作方式,可以保留鍵值,不使用額外記憶體,而且可能更容易理解。

<?php
if (function_exists('shuffle_with_keys')===false) {
function
shuffle_with_keys(&$array) {
/* 使用輔助陣列儲存新的順序 */
$aux = array();
/* 我們使用鍵的陣列 */
$keys = array_keys($array);
/* 我們將鍵打亂 */
shuffle($keys);
/* 我們迭代鍵的新順序 */
foreach($keys as $key) {
/* 我們按新的順序插入鍵值對 */
$aux[$key] = $array[$key];
/* 我們從舊陣列中移除元素以節省記憶體 */
unset($array[$key]);
}
/* 具有新順序的輔助陣列覆蓋舊變數 */
$array = $aux;
}
}
?>
DiosDe
3 年前
使用 random_int() 實作 shuffle()

<?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;
}
?>
To Top