PHP – 配列の最後の要素の判定にend()は使わない方がいい話

配列をforeachで回して、CSVを作成したり、SQL文を作成したいときに、最後の要素だけ、改行をつけたくなかったりとか、カンマをつけたくなかったりとかありますよね。
そんな時にググったりするとend()関数が見つかって、こいつで出来るかも、と思うかもしれませんが、罠があります。
というのもend()は正確には「配列の最後の要素の値を返す」という機能なので・・・

具体的に説明していきます。

最後の要素の判定にend()を使ってうまくいくパターン

例えば、以下のような場合。

$array = [0 => "aaa", 
    1 => "bbb", 
    2 => "ccc", 
    3 => "ddd", 
    4 => "eee", 
    5 => "fff"];

foreach($array as $k=>$v){
    if($v != end($array)){
        print "${k}=>${v} まだ最後じゃないよ\n";
    }else{
        print "${k}=>${v} これが最後だよ\n";
    }
}

実行結果は以下のようになります。

0=>aaa まだ最後じゃないよ
1=>bbb まだ最後じゃないよ
2=>ccc まだ最後じゃないよ
3=>ddd まだ最後じゃないよ
4=>eee まだ最後じゃないよ
5=>fff これが最後だよ

一見うまくいっているように見えます。

最後の要素の判定にend()を使ってうまくいかないパターン

もうお気づきかもしれませんが、end()は「配列の最後の要素の値を返す」ので、最初のパターンでは最後の要素の値、”fff”が返ってきていました。
が、配列要素内に重複する値が入っていると想定しない動きになってしまいます。
例えば下のようなパターン

$array = [0 => "aaa", 
    1 => "bbb", 
    2 => "ccc", 
    3 => "bbb", 
    4 => "ddd", 
    5 => "ccc"];

foreach($array as $k=>$v){
    if($v != end($array)){
        print "${k}=>${v} まだ最後じゃないよ\n";
    }else{
        print "${k}=>${v} これが最後だよ\n";
    }
}

この場合、下のようになってしまいます。

0=>aaa まだ最後じゃないよ
1=>bbb まだ最後じゃないよ
2=>ccc これが最後だよ
3=>bbb まだ最後じゃないよ
4=>ddd まだ最後じゃないよ
5=>ccc これが最後だよ

今度は最後の要素が”ccc”だったので、途中のkeyが2の要素の箇所でも引っ掛かってしまいますね・・・

素直にcount()を使う

回避するには素直にカウント用の変数を用意して、arrayをcount()するのがいいのかなーと思います。

さっきの例だとこんな感じ

$array = [0 => "aaa", 
    1 => "bbb", 
    2 => "ccc", 
    3 => "bbb", 
    4 => "ddd", 
    5 => "ccc"];

$cnt = 1;
$length = count($array);

foreach($array as $k=>$v){
    if($cnt < $length){
        print "${k}=>${v} まだ最後じゃないよ\n";
    }else{
        print "${k}=>${v} これが最後だよ\n";
    }
    $cnt++;
}

実行結果は↓になります

0=>aaa まだ最後じゃないよ
1=>bbb まだ最後じゃないよ
2=>ccc まだ最後じゃないよ
3=>bbb まだ最後じゃないよ
4=>ddd まだ最後じゃないよ
5=>ccc これが最後だよ

2 件のコメント

  1. ピンバック: いろいろな言語で配列の最後の要素 | IT技術情報局

  2. ピンバック: PHPで配列の最後の値を取得する | IT技術情報局

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です