Temukan elemen terakhir array saat menggunakan foreach loop di PHP


215

Saya menulis pembuat kueri SQL menggunakan beberapa parameter. Di Jawa, sangat mudah untuk mendeteksi elemen terakhir dari array dari dalam for loop dengan hanya memeriksa posisi array saat ini dengan panjang array.

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

Di PHP mereka memiliki indeks non-integer untuk mengakses array. Jadi, Anda harus mengulangi array menggunakan foreach loop. Ini menjadi bermasalah ketika Anda perlu mengambil beberapa keputusan (dalam kasus saya untuk menambahkan atau / dan parameter saat membangun kueri).

Saya yakin pasti ada cara standar untuk melakukan ini.

Bagaimana Anda mengatasinya dalam PHP?


2
Apakah Anda mencoba menentukan apakah Anda harus menyatukan "DAN" atau "ATAU" antara bagian-bagian dari klausa where
Darryl Hein

1
hanya menunjukkan bahwa Anda harus menyimpan total dalam variabel alih-alih memanggil metode untuk setiap iterasi. untuk (int i = 0, int t = arr.length; i <t; i ++).
OIS



Jawaban:


313

Sepertinya Anda menginginkan sesuatu seperti ini:

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

Yang sedang berkata, Anda tidak -memiliki iterate atas "array" menggunakan foreachdi php.


Saya pikir saya akan menggunakan solusi ini karena hampir mirip dengan kode yang saya posting. Bahkan jawaban Jeremy sangat pas tapi saya pikir itu menjadi sedikit rumit dibandingkan dengan yang ini. Saya belum menjalankan tes tetapi saya kira jawaban ini akan lebih cepat karena tidak mengekstraksi array kunci. Ini akan memiliki O (1) kecepatan
Vaibhav Kamble

18
$numItems = count($arr)trik tidak diperlukan dan mengurangi keterbacaan - dalam PHP tidak ada penalti kinerja untuk mengakses hitungan ($ arr) setiap kali. Alasannya adalah bahwa jumlah item disimpan secara internal sebagai bidang khusus di header array dan tidak dihitung saat itu juga. Trik ini berasal dari bahasa lain (C, Java?, ...).
johndodo

7
Itu menarik @johndodo bahwa tidak ada penalti kinerja untuk mengakses hitungan ($ arr) setiap kali. Apakah Anda memiliki tautan / sumber ke tempat optimasi khusus ini didokumentasikan? Terima kasih!
zuallauz

2
Agak menyedihkan bahwa di PHP solusi yang paling tepat untuk masalah ini terlihat agak tidak benar :(
kizzx2

1
@tomsihap $ i harus ditambahkan di dalam loop, bersamaan dengan iterasi array. $ i harus mewakili jumlah item dalam array, sehingga dapat digunakan untuk menentukan kapan item terakhir telah tercapai. Tanpa ++, loop hanya akan membandingkan "0" dengan jumlah total item.
Bobby Jack

201

Anda bisa mendapatkan nilai kunci terakhir dari array menggunakan end(array_keys($array))dan membandingkannya dengan kunci saat ini:

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

2
+1 Saya setuju - solusi lain bergantung pada array yang memiliki indeks numerik.
Patrick Glandien

19
Dalam pembelaan saya sendiri, jawaban saya tidak bergantung pada array memiliki tombol angka :)
Richard Levasseur

2
perbandingan string lebih lambat dari integer, dan tidak selalu akurat ketika membandingkan string ke integer (Anda setidaknya harus menggunakan ===). Saya memilih ini.
OIS

4
elegan, tetapi menyebabkan PEMBERITAHUAN KETAT karena "end" mengharapkan nilai referensi :(
Wiliam

10
Perbaiki untuk PEMBERITAHUAN KETAT:$lastKey = array_search(end($array), $array);
Ajax

44

mengapa begitu rumit?

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

Ini akan menambahkan, di balik setiap nilai kecuali yang terakhir!


2
Tidak jika $ input berikutnya berisi nilai boolean dari false, yang merupakan masalah utama dengan next ().
soulseekah

29
Kecuali saya salah, ini tidak berfungsi karena memanggil next () akan memajukan pointer array, jadi Anda melewatkan setiap elemen lainnya dalam loop.
Jordan Lev

2
Sepertinya tidak bekerja untuk saya. Elemen terakhir kedua tidak mendapatkan koma tetapi seharusnya.
zuallauz

1
Jika nilainya sama dengan bool false, itu tidak berfungsi. Juga tidak mencetak koma terakhir antara nilai kedua ke terakhir dan terakhir.
OIS

1
Catatan untuk siapa pun yang ingin menggunakan ini di PHP7 - pointer array tidak bergerak di loop foreach, dan ini tidak akan berfungsi.
Scott Flack

26

Ketika toEnd mencapai 0 itu berarti ia berada pada iterasi terakhir dari loop.

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

Nilai terakhir masih tersedia setelah loop, jadi jika Anda hanya ingin menggunakannya untuk lebih banyak barang setelah loop ini lebih baik:

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

Jika Anda tidak ingin memperlakukan nilai terakhir sebagai loop dalam khusus. Ini harus lebih cepat jika Anda memiliki array yang besar. (Jika Anda menggunakan kembali array setelah loop di dalam ruang lingkup yang sama Anda harus "menyalin" array terlebih dahulu).

//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";

Dan untuk menjawab pertanyaan awal Anda "dalam kasus saya untuk menambahkan atau / dan parameter sambil membangun kueri"; ini akan mengulang semua nilai, kemudian bergabung bersama-sama ke string dengan "dan" di antara mereka tetapi tidak sebelum nilai pertama atau setelah nilai terakhir:

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

2
Tentu saja akan melakukan - $ toEnd untuk setiap iterasi, itu intinya. Jika saya memindahkannya di luar loop, itu tidak akan berfungsi lagi.
OIS

Metode paling sederhana yang pernah digunakan. $lastValue = array_pop($array);Terima kasih.
Elias Nicolas

21

Sudah ada banyak jawaban, tetapi ada baiknya untuk melihat iterator juga, terutama karena telah diminta cara standar:

$arr = range(1, 3);

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

Anda mungkin menemukan sesuatu yang berfungsi lebih fleksibel untuk kasus lain juga.


Jawaban yang bagus Saya menghargai bahwa Anda menggunakan fitur bahasa yang dimaksudkan untuk tugas tersebut. i=0;dan ++i;selalu tampak seperti hacker dalam bahasa scripting seperti PHP.
CheddarMonkey

15

Salah satu caranya adalah mendeteksi apakah iterator memilikinya next. Jika tidak ada berikutnya yang melekat pada iterator itu berarti Anda berada di loop terakhir.

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

Saya pikir ini adalah cara termudah dan membutuhkan jumlah kode paling sedikit!
hai im zvaehn

1
Tidak berfungsi dengan PHP 7+ sebagai "Dalam PHP 7, foreach tidak menggunakan pointer array internal.".
Damien Debin

8

Jadi, jika array Anda memiliki nilai array unik, maka menentukan iterasi terakhir adalah sepele:

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

Seperti yang Anda lihat, ini berfungsi jika elemen terakhir hanya muncul sekali dalam array, jika tidak, Anda akan mendapatkan alarm palsu. Di dalamnya tidak, Anda harus membandingkan kunci (yang unik pasti).

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

Perhatikan juga operator coparision yang ketat, yang cukup penting dalam kasus ini.


ini cara yang tidak efisien.
Akal Sehat Anda

Nggak. Bukan itu. end () melakukan O (1). Ini juga lebih pendek dari solusi lain, dan terbaca dengan baik -> Jika elemen sama dengan akhir array, tulis "Terakhir".
Rok Kralj

Ini lebih dari dua kali lebih lambat dari contoh pertama dan terakhir saya untuk nilai 100000.
OIS

5

Asumsikan Anda memiliki array yang disimpan dalam variabel ...

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

Ini sangat sederhana dan bermanfaat. Saya hanya akan menghitung array terlebih dahulu di luar foreach loop sehingga program tidak harus menghitung setiap kali fungsi foreach mengevaluasi setiap item.
Pathros

3
Ini tidak akan berfungsi pada array asosiatif. $ key tidak selalu angka.
Jonathan

5

untuk mendapatkan elemen pertama dan terakhir dari foreach array

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

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

4

Anda masih dapat menggunakan metode itu dengan array asosiatif:

$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
Silakan ubah $ key = $ array [$ i]; ke $ key = $ keys [$ i]; di pertama untuk loop.
Narek

4

Jika Anda perlu melakukan sesuatu untuk setiap elemen kecuali yang pertama atau yang terakhir dan hanya jika ada lebih dari satu elemen dalam array, saya lebih suka solusi berikut.

Saya tahu ada banyak solusi di atas dan diposting bulan / satu tahun sebelum saya, tetapi ini adalah sesuatu yang saya rasa cukup elegan. Periksa setiap loop juga merupakan cek boolean yang berlawanan dengan cek "i = (count-1)" numerik, yang memungkinkan lebih sedikit overhead.

Struktur loop mungkin terasa aneh, tetapi Anda dapat membandingkannya dengan urutan thead (awal), tfoot (end), tbody (current) dalam tag tabel HTML.

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

Misalnya, dalam istilah pengembangan web, jika Anda ingin menambahkan border-bottom ke setiap elemen kecuali yang terakhir di daftar tidak berurutan (ul), maka Anda bisa menambahkan border-top ke setiap elemen kecuali yang pertama (CSS: anak pertama, didukung oleh IE7 + dan Firefox / Webkit mendukung logika ini, sedangkan: anak terakhir tidak didukung oleh IE7).

Anda dapat merasa bebas untuk menggunakan kembali variabel $ first untuk masing-masing dan setiap loop bersarang juga dan semuanya akan berfungsi dengan baik karena setiap loop membuat $ first false selama proses pertama dari iterasi pertama (sehingga istirahat / pengecualian tidak akan menyebabkan masalah) .

$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;

Contoh output:

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)

Thanx, ini solusi favorit saya! Ini sangat fleksibel dan biaya hanya boolean. BTW, saya pikir ini akan berfungsi untuk array yang mengandung setidaknya satu elemen juga (tidak hanya lebih dari satu elemen).
jc

4

Ini harus menjadi cara mudah untuk menemukan elemen terakhir:

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

Referensi: Tautan


- broken link -
T30

3

Saya memiliki perasaan yang kuat bahwa pada akar dari "masalah XY" OP ini hanya ingin implode()berfungsi.


1
benar. Ada beberapa kasus di mana meledak tidak praktis. Bayangkan misalnya mencoba menanamkan string panjang html dengan banyak variabel dinamis di dalamnya. Tentu, Anda dapat melakukan ob_start / ob_get_clean di atasnya, atau hanya membangunnya sebagai $ str = '...'. Tapi, ada saat-saat ini bisa dianggap hanya sedikit berlebihan
Alastair Brayne

3

Karena niat Anda menemukan array EOF hanya untuk lem. Kenali taktik di bawah ini. Anda tidak perlu meminta 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

Sepertinya Anda menginginkan sesuatu seperti ini:

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

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

2
Menggunakan nilai biasanya bukan ide yang baik karena tidak akan berfungsi dengan baik jika array memiliki dua nilai yang identik.
orrd

2

Jangan tambahkan koma setelah nilai terakhir:

Array:

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

Fungsi:

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

Hasil:

print $result;

lorem, ipsum, dolor, sit, amet


1

Anda dapat melakukan hitungan ().

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

atau jika Anda HANYA mencari elemen terakhir, Anda bisa menggunakan end ().

end(arr);

mengembalikan hanya elemen terakhir.

dan, ternyata, Anda BISA mengindeks array php dengan bilangan bulat. Sangat senang dengan itu

arr[1];

1
Kelemahan pada akhirnya (arr) adalah ia menetapkan pointer internal array ke elemen terakhir ..
Vijay

Tidak, Anda TIDAK HARUS menggunakan bilangan bulat untuk mengakses array kecuali Anda tahu bahwa kuncinya adalah numerik dan berurutan. Pertimbangkan: $a = array(0=>'A', 2=>'B', 'aaa'=>'C'). Apa yang Anda dapatkan jika Anda mengakses $a[count($a)-1]?
johndodo

1

Anda juga dapat melakukan sesuatu seperti ini:

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

     // more code
}

end mengembalikan nilai bukan array, jadi cara Anda membuatnya tidak berfungsi. perbandingan string juga lebih lambat dari integer.
OIS

Kamu benar. itu harus akhir ($ elemen); $ endKey = key ($ elements);
KOGI

1

Saya agak suka yang berikut ini karena saya merasa cukup rapi. Mari kita asumsikan kita sedang membuat string dengan pemisah antara semua elemen: misalnya a, b, c

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

membuatnya lebih sederhana tanpa mendeklarasikan $ pertama; gunakan foreach ($ item sebagai $ key => $ item) lalu $ str = ($ key == 0)?
Milan Rilex Ristic

1
foreach ($array as $key => $value) {

  $class = ( $key !== count( $array ) -1 ) ? " class='not-last'" : " class='last'";

  echo "<div{$class}>";
  echo "$value['the_title']";
  echo "</div>";

}

Referensi


0

Berikut cara lain untuk melakukannya:

$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

Jika saya mengerti Anda, maka yang Anda butuhkan adalah membalikkan array dan mendapatkan elemen terakhir dengan perintah pop:

   $rev_array = array_reverse($array);

   echo array_pop($rev_array);

0

Anda juga dapat mencoba ini untuk membuat kueri Anda ... ditampilkan di sini dengan 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

Untuk skrip pembuatan kueri SQL, atau apa pun yang melakukan tindakan berbeda untuk elemen pertama atau terakhir, itu jauh lebih cepat (hampir dua kali lebih cepat) untuk menghindari menggunakan pemeriksaan variabel yang tidak perlu.

Solusi yang diterima saat ini menggunakan loop dan centang dalam loop yang akan dibuat every_single_iteration, cara (cepat) yang benar untuk melakukan ini adalah sebagai berikut:

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

Patokan kecil buatan sendiri menunjukkan yang berikut:

test1: 100000 menjalankan model morg

waktu: 1869,3430423737 milidetik

test2: 100000 menjalankan model jika bertahan

waktu: 3235.6359958649 milidetik


0

Cara lain adalah mengingat hasil siklus putaran sebelumnya dan menggunakannya sebagai hasil akhir:

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

0

Saya pribadi menggunakan jenis konstruksi ini yang memungkinkan penggunaan yang mudah dengan elemen html <ul> dan <li>: cukup ubah kesetaraan untuk properti lain ...

Array tidak dapat berisi item palsu tetapi semua item lainnya yang dilemparkan ke dalam boolean palsu.

$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

Anda dapat secara langsung mendapatkan indeks terakhir dengan:

$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

Inilah solusi saya: Cukup hitung jumlah array Anda, minus 1 (sejak mereka mulai 0).

$lastkey = count($array) - 1;
foreach($array as $k=>$a){
    if($k==$lastkey){
        /*do something*/
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.