2月 242012
 

すでに要素が格納されている配列に後から添え字 0 の要素を作っても、添え字 0 の要素は先頭の要素にはなりません。
そのため、「その配列から添え字 0 の要素を取り除き」「添え字を 0 から振り直す」ために array_shift を使用すると、意図した結果になりません。

この場合は添え字 0 の要素があれば unset し、なければそのままで array_values を使用すると添え字を 0 から振り直せます。

結論は以上ですが、詳しく見るために以下の要件を想定します。

  • 配列は for 文で処理するため 0 から 1 ずつ添え字が増えていく形で作りたい。
  • 場合によって 0 番目に優先的に入る要素がある。

それってどんなとき?聖闘士星矢で説明してくれ。

  • 4 人の聖闘士が戦っている。
  • ある人物がピンチのときに助けにきて大活躍してくれる聖闘士がいる。
  • 戦いの中で全員がセブンセンシズに目覚める。

ということで、以下のコードを書き、4 人もしくは 5 人の聖闘士をセブンセンシズに目覚めさせてみましょう。

// 聖闘士集合
$saints = array(
    'Pegasus' => 'Seiya', 
    'Dragon' => 'Shiryu', 
    'Cyguns' => 'Hyouga', 
    'Andromeda' => 'Shun'
);
// 聖闘士、闘いに赴く
$fightingSaints = array();
$i = 0;
foreach ($saints as $saint) {
    $fightingSaints[++$i] = $saint;
}
// 瞬がピンチだ
if ($shunIsInAPinch) {
    // 兄貴、颯爽と現れ先頭に躍り出る
    $fightingSaints[0] = 'Ikki';
} else {
    $fightingSaints[0] = null;
    array_shift($fightingSaints);
}
// 聖闘士、セブンセンシズに目覚める
for ($i = 0; $i < count($fightingSaints); $i++) {
    seventhSense($fightingSaints&#91;$i&#93;);
}
&#91;/PHP&#93;

もし $shunIsInAPinch が true の場合は
<ol>
<li>Ikki</li>
<li>Seiya</li>
<li>Shiryu</li>
<li>Hyouga</li>
<li>Shun</li>
</ol>
の 5 人全員がセブンセンシズに目覚めることができます。
じゃあ $shunIsInAPinch が false の場合どうなるか。Ikki が来ないので 4 人がセブンセンシズに目覚めるはずです。ところが…
<ol>
<li>Shiryu</li>
<li>Hyouga</li>
<li>Shun</li>
</ol>
哀れ、Seiya はアナザーディメンションで異次元に飛ばされました。
何が悪かったのでしょうか?
コードの 21 行目の直後で $fightingSaints の中身を見てみましょう。

$shunIsInAPinch が true のとき
[PHP]
Array
(
    [1] => Seiya
    [2] => Shiryu
    [3] => Hyouga
    [4] => Shun
    [0] => Ikki
)

先頭に躍り出たと思われた Ikki は一番後ろに。鳳凰幻魔拳を受けましたね。

$shunIsInAPinch が false のとき

Array
(
    [0] => Shiryu
    [1] => Hyouga
    [2] => Shun
    [3] => 
)

$shunIsInAPinch が false のとき、コードの 19 行目では何が起きているのか?

Array
(
    [1] => Seiya
    [2] => Shiryu
    [3] => Hyouga
    [4] => Shun
    [0] => 
)

添え字 0 の要素を後から作っても、先頭は相変わらず添え字 1 の Seiya で、array_shift によって 先頭の Seiya がアナザーディメンションされてしまう、というわけですね。
19 ~ 20 行目は素直にこう書き換えましょう。

$fightingSaints = array_values($fightingSaints);

これで Ikki が来なくてもみんなセブンセンシズに目覚めることができます。

  1. Seiya
  2. Shiryu
  3. Hyouga
  4. Shun

聖闘士は二度同じ技は受けませんので、このロジックで失敗することはもうありませんね。

 Posted by at 1:13 AM