PHPのshuffle()が連想配列では使えない件について(@2011/10/7 0:12)

↓こんな連想配列があったとして、
$AmericanLeagueEastDivisionTeams = array(
'BAL' => array('city' => 'Baltimore', 'name' => 'Orioles'),
'BOS' => array('city' => 'Boston', 'name' => 'Red Sox'),
'NYY' => array('city' => 'New York', 'name' => 'Yankees'),
'TB' => array('city' => 'Tampa Bay', 'name' => 'Rays'),
'TOR' => array('city' => 'Toronto', 'name' => 'Blue Jays'),
);

shuffle()してみると…
shuffle($AmericanLeagueEastDivisionTeams);
var_export($AmericanLeagueEastDivisionTeams);

↓結果(見やすいように整形済み)
array (
0 => array ('city' => 'Boston', 'name' => 'Red Sox'),
1 => array ('city' => 'Toronto', 'name' => 'Blue Jays'),
2 => array ('city' => 'New York', 'name' => 'Yankees'),
3 => array ('city' => 'Tampa Bay', 'name' => 'Rays'),
4 => array ('city' => 'Baltimore', 'name' => 'Orioles')
)

はい。キーが破棄されて、数字キーに割り当て直されちゃいます。

じゃあ、array_rand()でランダム順のキーを取得しよう、と思った。

$len = count($AmericanLeagueEastDivisionTeams);
$abbrs = array_rand($AmericanLeagueEastDivisionTeams, $len);
var_export($abbrs);

↓結果
array (
0 => 'BAL',
1 => 'BOS',
2 => 'NYY',
3 => 'TB',
4 => 'TOR',
)

よし、この「キーがランダム順に入った配列」を使おう。
…あれ?並べ変わってなくね?
たまたまかな(^o^;

再実行→やっぱりおんなじ→再々実行→やっぱりおんなじ→(無限ループ)
全件取得する場合は並べ換えて紅の豚?
マニュアルに書いといてよ。そんなこと。。

まあ、array_keys()を使ってそれをshuffle()すれば同じ事はできるか。

$abbrs = array_keys($AmericanLeagueEastDivisionTeams);
shuffle($abbrs);
var_export($abbrs);

↓結果
array (
0 => 'NYY',
1 => 'BOS',
2 => 'TB',
3 => 'BAL',
4 => 'TOR',
)

当然ながらうまくいく。再実行すればまた並び変わる。

せっかくだから、関数化しておくか。
PHPオリジナルの命名則にあわせて、ashuffle()と名付ける(※)。
オリジナルのshuffle()が並べ替えが成功したかどうかを返しているので、とりあえずtrueを返すことにする。

function ashuffle(&$array) {
$keys = array_keys($array);
shuffle($keys);

$res = array();
for ($i = 0, $_l = count($keys); $i < $_l; $i++) {
$res[$keys[$i]] = $array[$keys[$i]];
}

$array = $res;
return true;
}

これで、

ashuffle($AmericanLeagueEastDivisionTeams);

$rank = 0;
foreach ($AmericanLeagueEastDivisionTeams as $abbr => $team) {
printf("%d: %s %s (%s)\n", ++$rank, $team['city'], $team['name'], $abbr);
}

↓結果
1: New York Yankees (NYY)
2: Baltimore Orioles (BAL)
3: Tampa Bay Rays (TB)
4: Boston Red Sox (BOS)
5: Toronto Blue Jays (TOR)

成功。


※:蛇足。
この記事を書く時に、そういえば、もうすでに誰かが作ってるよな。"ashuffle()"って名前で。
っと思ってググってみたら、どうやら無いみたい。。
ってことは、このページがひっかかるようになるんだ。ウシシ( ̄ー ̄)