PHPでforeachループを使用しているときに配列の最後の要素を見つける


215

いくつかのパラメーターを使用してSQLクエリの作成者を書いています。Javaでは、配列の長さで現在の配列位置を確認するだけで、forループ内から配列の最後の要素を検出するのは非常に簡単です。

for(int i=0; i< arr.length;i++){
     boolean isLastElem = i== (arr.length -1) ? true : false;        
}

PHPでは、配列にアクセスするための非整数のインデックスがあります。したがって、foreachループを使用して配列を反復処理する必要があります。これは、何らかの決定を行う必要がある場合に問題になります(私の場合、クエリの作成中にパラメータまたはパラメータを追加することになります)。

これを行うための標準的な方法がいくつかあるに違いないと私は確信しています。

これをPHPでどのように解決しますか?


2
where句のパーツ間で「AND」または「OR」を連結する必要があるかどうかを判断しようとしていますか?
ダリルハイン

1
繰り返しごとにメソッドを呼び出すのではなく、変数に合計を格納する必要があることを指摘するだけです。for(int i = 0、int t = arr.length; i <t; i ++)。
OIS


このソリューションを
ご覧ください

回答:


313

あなたはこのようなものが欲しいようです:

$numItems = count($arr);
$i = 0;
foreach($arr as $key=>$value) {
  if(++$i === $numItems) {
    echo "last index!";
  }
}    

そうは言ってもforeach、phpで「配列」を反復処理する必要はありません。


私が投稿したコードとほとんど同じなので、私はこのソリューションに行くと思います。ジェレミーの答えでさえぴったりですが、これに比べて少し複雑になっていると思います。私はテストを実行していませんが、キーの配列を抽出しないので、この答えはより高速になると思います。これはO(1)の速度になります
Vaibhav Kamble 2009年

18
$numItems = count($arr)トリックは必要なく、読みやすさが低下します-PHPでは、count($ arr)にアクセスするたびにパフォーマンスが低下することはありません。その理由は、アイテム数は配列ヘッダーの特別なフィールドとして内部的に保存され、その場で計算されないためです。このトリックは他の言語(C、Java?、...)から来ています。
johndodo

7
@johndodoが興味深いのは、毎回count($ arr)にアクセスしてもパフォーマンスが低下しないことです。この特定の最適化が文書化されている場所へのリンク/ソースはありますか?ありがとう!
zuallauz 2012年

2
PHPでこの問題に対する最も適切な解決策がかなり洗練されていないように見えるのはかなり悲しいです:(
kizzx2

1
@tomsihap $ iは、配列の反復と並行して、ループ内でインクリメントする必要があります。$ iは、配列内の項目の数を表す必要があります。これにより、最後の項目に到達したかどうかを判別するために使用できます。++がなければ、ループは「0」とアイテムの総数を比較するだけです。
ボビージャック

201

を使用end(array_keys($array))して配列の最後のキーの値を取得し、それを現在のキーと比較できます。

$last_key = end(array_keys($array));
foreach ($array as $key => $value) {
    if ($key == $last_key) {
        // last element
    } else {
        // not last element
    }
}

2
+1同意する-他の解決策は、数値インデックスを持つ配列に依存しています。
Patrick Glandien 2009年

19
私の弁護では、私の答えは、数値キーを持つ配列に依存していません:)
Richard Levasseur

2
文字列の比較は整数よりも遅く、文字列を整数と比較するときに常に正確であるとは限りません(少なくとも===を使用する必要があります)。これを投票します。
OIS

4
エレガントですが、 "end"は参照値:(
Wiliam

10
STRICT NOTICEの修正:$lastKey = array_search(end($array), $array);
Ajax

44

なぜそんなに複雑なのですか?

foreach($input as $key => $value) {
    $ret .= "$value";
    if (next($input)==true) $ret .= ",";
}

これにより、最後の値を除くすべての値の後ろにが追加されます。


2
次の$ inputにブール値falseが含まれている場合は、next()の主要な問題です。
soulseekah

29
誤解しない限り、next()を呼び出すと配列ポインターが進むため、これは機能しません。ループ内の他のすべての要素をスキップします。
ジョーダンレフ

2
うまくいかないようです。最後から2番目の要素はコンマを取得しませんが、取得する必要があります。
zuallauz

1
値がbool falseに等しい場合、機能しません。また、2番目から最後までの値と最後の値の間の最後のコンマを印刷しません。
OIS

1
これをPHP7で使用したい人への注意-配列ポインタはforeachループ内で移動しないため、これは機能しません。
Scott Flack

26

toEndが0に到達すると、ループの最後の反復であることを意味します。

$toEnd = count($arr);
foreach($arr as $key=>$value) {
  if (0 === --$toEnd) {
    echo "last index! $value";
  }
}

最後の値はループ後も引き続き使用できるので、ループの後でさらに多くの目的に使用したい場合は、これが適切です。

foreach($arr as $key=>$value) {
  //something
}
echo "last index! $key => $value";

最後の値を特別な内部ループとして扱いたくない場合。配列が大きい場合は、この方が高速です。(同じスコープ内でループの後に配列を再利用する場合は、最初に配列を「コピー」する必要があります)。

//If you use this in a large global code without namespaces or functions then you can copy the array like this:
//$array = $originalArrayName; //uncomment to copy an array you may use after this loop

//end($array); $lastKey = key($array); //uncomment if you use the keys
$lastValue = array_pop($array);

//do something special with the last value here before you process all the others?
echo "Last is $lastValue", "\n";

foreach ($array as $key => $value) {
    //do something with all values before the last value
    echo "All except last value: $value", "\n";
}

//do something special with the last value here after you process all the others?
echo "Last is $lastValue", "\n";

そして、あなたの元の質問に答えるために、「私のケースでは、クエリの構築中にパラメータまたはパラメータを追加する」; これはすべての値をループしてから、それらを「と」の間にある文字列に結合しますが、最初の値の前または最後の値の後ではありません。

$params = [];
foreach ($array as $value) {
    $params[] = doSomething($value);
}
$parameters = implode(" and ", $params);

2
もちろん、反復ごとに-$ toEndを実行します。これがポイントです。ループの外に移動すると、機能しなくなります。
OIS

これまでに使用された最も簡単な方法。$lastValue = array_pop($array);ありがとうございました。
エリアスニコラス

21

すでに多くの答えがありますが、特に標準的な方法が求められているので、イテレータも検討する価値があります。

$arr = range(1, 3);

$it = new CachingIterator(new ArrayIterator($arr));
foreach($it as $key => $value)
{
  if (!$it->hasNext()) echo 'Last:';
  echo $value, "\n";
}

他のケースでもより柔軟に機能するものが見つかるかもしれません。


すばらしい答えです。タスクに使用する言語の機能をご利用いただきありがとうございます。i=0;そして、++i;PHPのようなスクリプト言語では常にハックのように見えてきました。
CheddarMonkey 2018年

15

1つの方法は、イテレータにがあるかどうかを検出することですnext。イテレータに次がアタッチされていない場合は、最後のループにいることを意味します。

foreach ($some_array as $element) {
    if(!next($some_array)) {
         // This is the last $element
    }
}

これが最も簡単な方法であり、必要なコードの量が最も少ないと思います!
hi im zvaehn

1
「PHP 7では、foreachは内部配列ポインターを使用しません。」のように、PHP 7以降では機能しません。
Damien Debin

8

したがって、配列に一意の配列値がある場合、最後の反復の決定は簡単です。

foreach($array as $element) {
    if ($element === end($array))
        echo 'LAST ELEMENT!';
}

ご覧のとおり、これは最後の要素が配列に一度だけ表示されている場合に機能します。それ以外の場合は、誤ったアラームが表示されます。それではありません、あなたはキーを比較する必要があります(確かにユニークです)。

foreach($array as $key => $element) {
    end($array);
    if ($key === key($array))
        echo 'LAST ELEMENT!';
}

また、この場合は非常に重要な厳密な比較演算子にも注意してください。


これは非常に非効率的な方法です。
常識

いいえ。そうではない。end()はO(1)を実行します。また、他のソリューションよりも短く、読みやすくなります->要素が配列の最後と等しい場合は、「最後」と書き込みます。
Rok Kralj

これは、100000の値の最初と最後の例の2倍以上遅くなります。
OIS、2015

5

配列が変数に格納されていると仮定します...

foreach($array as $key=>$value) 
{ 
    echo $value;
    if($key != count($array)-1) { echo ", "; }
}

これは非常にシンプルで便利です。foreachループの外で最初に配列を数えるだけなので、プログラムがforeach関数が各項目を評価するたびに数える必要はありません。
Pathros 2015

3
これは連想配列では機能しません。$ keyは常に数値であるとは限りません。
ジョナサン

5

foreach配列から最初と最後の要素を取得する

foreach($array as $value) {
    if ($value === reset($array)) {
        echo 'FIRST ELEMENT!';
    }

    if ($value === end($array)) {
        echo 'LAST ITEM!';
    }
}

4

連想配列でもこの方法を使用できます。

$keys = array_keys($array);
for ($i = 0, $l = count($array); $i < $l; ++$i) {
    $key = $array[$i];
    $value = $array[$key];
    $isLastItem = ($i == ($l - 1));
    // do stuff
}

// or this way...

$i = 0;
$l = count($array);
foreach ($array as $key => $value) {
    $isLastItem = ($i == ($l - 1));
    // do stuff
    ++$i;
}

1
$ key = $ array [$ i]を変更してください。to $ key = $ keys [$ i]; 最初のforループで。
Narek、2011年

4

最初または最後以外のすべての要素に対して何かを行う必要があり、配列に複数の要素がある場合のみ、次の解決策をお勧めします。

上記には多くの解決策があり、数か月前/ 1年前に投稿されていますが、これはそれ自体がかなりエレガントだと感じています。すべてのループのチェックも、数値の "i =(count-1)"チェックとは対照的にブールチェックであり、オーバーヘッドを減らすことができます。

ループの構造は扱いにくいかもしれませんが、HTMLテーブルタグのthead(先頭)、tfoot(終了)、tbody(現在)の順序と比較できます。

$first = true;
foreach($array as $key => $value) {
    if ($first) {
        $first = false;
        // Do what you want to do before the first element
        echo "List of key, value pairs:\n";
    } else {
        // Do what you want to do at the end of every element
        // except the last, assuming the list has more than one element
        echo "\n";
    }
    // Do what you want to do for the current element
    echo $key . ' => ' . $value;
}

たとえば、Web開発用語で、無秩序リストの最後の要素(ul)を除くすべての要素にborder-bottomを追加する場合は、最初の要素(CSS を除く)を除くすべての要素にborder-topを追加できます。 IE7 +およびFirefox / Webkitでサポートされているfirst-childはこのロジックをサポートしていますが、:last-childはIE7ではサポートされていません)。

ネストされたループごとに$ first変数を自由に再利用することもできます。最初の反復の最初のプロセス中にすべてのループが$ firstをfalseにするため、問題はうまく機能します(ブレーク/例外によって問題が発生することはありません)。 。

$first = true;
foreach($array as $key => $subArray) {
    if ($first) {
        $string = "List of key => value array pairs:\n";
        $first = false;
    } else {
        echo "\n";
    }

    $string .= $key . '=>(';
    $first = true;
    foreach($subArray as $key => $value) {
        if ($first) {
            $first = false;
        } else {
            $string .= ', ';
        }
        $string .= $key . '=>' . $value;
    }
    $string .= ')';
}
echo $string;

出力例:

List of key => value array pairs:
key1=>(v1_key1=>v1_val1, v1_key2=>v1_val2)
key2=>(v2_key1=>v2_val1, v2_key2=>v2_val2, v2_key3=>v2_val3)
key3=>(v3_key1=>v3_val1)

ありがとう、これは私のお気に入りのソリューションです!非常に柔軟性があり、ブール値のみがかかります。ところで、私は、これは、配列が含むために働くだろうと思い、少なくともあまりにも(だけではなく、一つの要素を複数の一つの要素)。
jc

4

これは、最後の要素を見つける簡単な方法です。

foreach ( $array as $key => $a ) {
    if ( end( array_keys( $array ) ) == $key ) {
        echo "Last element";
     } else {
        echo "Just another element";
     }
}  

参考:リンク


-リンク切れ
T30 2017年

3

私はこの「XY問題」の根本にあるOPがちょうどimplode()機能したかったと強く感じています。


1
本当。ただし、内破が実際的ではない場合もあります。たとえば、多くの動的変数を含む長いHTML文字列を爆破しようとしていると想像してみてください。もちろん、ob_start / ob_get_cleanを実行することも、$ str = '...'としてビルドすることもできます。しかし、これはちょうど少しやり過ぎと考えることができる時間がある
アラステアBrayne

3

EOF配列を見つけるというあなたの意図は接着剤のためだけです。以下の戦術を紹介します。EOFは必要ありません。

$given_array = array('column1'=>'value1',
                     'column2'=>'value2',
                     'column3'=>'value3');

$glue = '';
foreach($given_array as $column_name=>$value){
    $where .= " $glue $column_name = $value"; //appending the glue
    $glue   = 'AND';
}
echo $where;

o / p:

column1 = value1 AND column2 = value2 AND column3 = value3


2

あなたはこのようなものが欲しいようです:

$array = array(
    'First',
    'Second',
    'Third',
    'Last'
);

foreach($array as $key => $value)
{
    if(end($array) === $value)
    {
       echo "last index!" . $value;
    }
}

2
配列に2つの同じ値がある場合、値が適切に機能しないため、通常は値を使用することはお勧めできません。
2014年

2

最後の値の後にコンマを追加しないでください:

配列:

$data = ['lorem', 'ipsum', 'dolor', 'sit', 'amet'];

関数:

$result = "";
foreach($data as $value) {
    $resut .= (next($data)) ? "$value, " : $value;
}

結果:

print $result;

lorem、ipsum、doror、sit、amet


1

あなたはcount()を行うことができます。

for ($i=0;$i<count(arr);$i++){
    $i == count(arr)-1 ? true : false;
}

または、最後の要素のみを探している場合は、end()を使用できます。

end(arr);

最後の要素のみを返します。

そして結局のところ、整数でphp配列にインデックスを付けることができます。それは完全に満足しています

arr[1];

1
終了(ARR)での欠点は、それが最後の要素を配列の内部ポインタを設定します..です
ビジェイ

いいえ、キーが数値でシーケンシャルであることがわかっている場合を除いて、配列へのアクセスに整数を使用することはできません。検討してください$a = array(0=>'A', 2=>'B', 'aaa'=>'C')。アクセスすると何が得られます$a[count($a)-1]か?
johndodo

1

次のようなこともできます:

end( $elements );
$endKey = key($elements);
foreach ($elements as $key => $value)
{
     if ($key == $endKey) // -- this is the last item
     {
          // do something
     }

     // more code
}

endは配列ではなく値を返すため、作成した方法は機能しません。文字列の比較も整数よりも遅くなります。
OIS、

あなたが正しいです。end($ elements);である必要があります。$ endKey = key($ elements);
KOGI 2009

1

結構すっきりしているので、次のような感じです。すべての要素の間にセパレーターがある文字列を作成しているとしましょう:例a、b、c

$first = true;
foreach ( $items as $item ) {
    $str = ($first)?$first=false:", ".$item;
}

$ firstを宣言せずに、より単純にします。foreach($ items as $ key => $ item)、次に$ str =($ key == 0)?
Milan Rilex Ristic


0

これは、別の方法で行うことができます。

$arr = range(1, 10);

$end = end($arr);
reset($arr);

while( list($k, $v) = each($arr) )
{
    if( $n == $end )
    {
        echo 'last!';
    }
    else
    {
        echo sprintf('%s ', $v);
    }
}

0

私があなたを理解しているなら、必要なのは配列を逆にして、最後の要素をpopコマンドで取得することだけです。

   $rev_array = array_reverse($array);

   echo array_pop($rev_array);

0

これを試してクエリを作成することもできます... INSERTでここに表示されています

<?php
 $week=array('one'=>'monday','two'=>'tuesday','three'=>'wednesday','four'=>'thursday','five'=>'friday','six'=>'saturday','seven'=>'sunday');
 $keys = array_keys($week);
 $string = "INSERT INTO my_table ('";
 $string .= implode("','", $keys);
 $string .= "') VALUES ('";
 $string .= implode("','", $week);
 $string .= "');";
 echo $string;
?>

0

SQLクエリ生成スクリプト、または最初の要素と最後の要素に対して異なるアクションを実行するものの場合、不要な変数チェックの使用を回避する方がはるかに高速(ほぼ2倍高速)です。

現在受け入れられているソリューションは、ループとevery_single_iterationになるループ内のチェックを使用します。これを行う正しい(高速な)方法は次のとおりです。

$numItems = count($arr);
$i=0;
$firstitem=$arr[0];
$i++;
while($i<$numItems-1){
    $some_item=$arr[$i];
    $i++;
}
$last_item=$arr[$i];
$i++;

少し手作りのベンチマークは次のことを示しています。

test1:モデルmorgの10万回の実行

時間:1869.3430423737ミリ秒

test2:最後であればモデルの100000回の実行

時間:3235.6359958649ミリ秒


0

もう1つの方法は、前のループサイクルの結果を記憶し、それを最終結果として使用することです。

    $result = $where = "";
    foreach ($conditions as $col => $val) {
        $result = $where .= $this->getAdapter()->quoteInto($col.' = ?', $val);
        $where .=  " AND ";
    }
    return $this->delete($result);

0

私は個人的にこのような構造を使用しており、html <ul>要素と<li>要素を簡単に使用できます。他のプロパティの等価性を変更するだけです...

配列にfalseアイテムを含めることはできませんが、falseブール値にキャストされる他のすべてのアイテムを含めることはできません。

$table = array( 'a' , 'b', 'c');
$it = reset($table);
while( $it !== false ) {
    echo 'all loops';echo $it;
    $nextIt = next($table);
    if ($nextIt === false || $nextIt === $it) {
            echo 'last loop or two identical items';
    }
    $it = $nextIt;
}

0

次のようにして、最後のインデックスを直接取得できます。

$numItems = count($arr);

echo $arr[$numItems-1];


0
<?php foreach($have_comments as $key => $page_comment): ?>
    <?php echo $page_comment;?>
    <?php if($key+1<count($have_comments)): ?> 
        <?php echo ', '; ?>
    <?php endif;?>
<?php endforeach;?>

0

これが私の解決策です:配列の数から1を引いた数を取得します(0から始まるため)。

$lastkey = count($array) - 1;
foreach($array as $k=>$a){
    if($k==$lastkey){
        /*do something*/
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.