Suchen Sie das letzte Element eines Arrays, während Sie eine foreach-Schleife in PHP verwenden

215

Ich schreibe einen SQL-Abfrageersteller mit einigen Parametern. In Java ist es sehr einfach, das letzte Element eines Arrays aus der for-Schleife heraus zu erkennen, indem Sie einfach die aktuelle Array-Position mit der Array-Länge überprüfen.

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

In PHP haben sie nicht ganzzahlige Indizes, um auf Arrays zuzugreifen. Sie müssen also mit einer foreach-Schleife über ein Array iterieren. Dies wird problematisch, wenn Sie eine Entscheidung treffen müssen (in meinem Fall das Anhängen oder / und Parameter beim Erstellen einer Abfrage).

Ich bin sicher, dass es dafür einen Standard geben muss.

Wie löst man das in PHP?

Vaibhav Kamble
quelle
2
Versuchen Sie festzustellen, ob Sie ein "UND" oder "ODER" zwischen Teilen einer where-Klausel setzen sollten?
Darryl Hein
1
Ich möchte nur darauf hinweisen, dass Sie die Summe in einer Variablen speichern sollten, anstatt für jede Iteration eine Methode aufzurufen. für (int i = 0, int t = arr.length; i <t; i ++).
OIS
Schauen Sie sich diese Lösung an: stackoverflow.com/a/29474468/1478566
vbarbarosh
benutze end (arrray) benutze ähnliche Antworten
Visakh B Sujathan

Antworten:

313

Es hört sich so an, als ob Sie so etwas wollen:

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

Davon abgesehen müssen Sie nicht über ein "Array" iterieren, das foreachin PHP verwendet wird.

Richard Levasseur
quelle
Ich denke, ich werde mich für diese Lösung entscheiden, da sie dem von mir geposteten Code fast ähnlich ist. Sogar Jeremys Antwort passt gut, aber ich denke, sie ist im Vergleich zu dieser wenig komplex geworden. Ich habe keine Tests durchgeführt, aber ich denke, diese Antwort wird schneller sein, da sie kein Array von Schlüsseln extrahiert. Diese soll O (1) Geschwindigkeit haben
Vaibhav Kamble
18
$numItems = count($arr)Trick ist nicht erforderlich und verringert die Lesbarkeit - in PHP gibt es keine Leistungseinbußen für den Zugriff auf count ($ arr) jedes Mal. Der Grund dafür ist, dass die Anzahl der Elemente intern als spezielles Feld im Array-Header gespeichert und nicht im laufenden Betrieb berechnet wird. Dieser Trick stammt aus anderen Sprachen (C, Java ?, ...).
Johndodo
7
Das ist interessant @johndodo, dass es keine Leistungseinbußen für den Zugriff auf count ($ arr) jedes Mal gibt. Haben Sie Links / Quellen, zu denen diese spezielle Optimierung dokumentiert ist? Vielen Dank!
zuallauz
2
Es ist ziemlich traurig, dass in PHP die korrekteste Lösung für dieses Problem ziemlich unelegant aussieht :(
kizzx2
1
@tomsihap $ i muss innerhalb der Schleife zusammen mit der Array-Iteration inkrementiert werden. $ i muss die Nummer des Elements im Array darstellen, damit bestimmt werden kann, wann das letzte Element erreicht wurde. Ohne ++ würde die Schleife immer nur "0" mit der Gesamtzahl der Elemente vergleichen.
Bobby Jack
201

Sie können den Wert des letzten Schlüssels des Arrays mithilfe von ermitteln end(array_keys($array))und mit dem aktuellen Schlüssel vergleichen:

$last_key = end(array_keys($array));
foreach ($array as $key => $value) {
    if ($key == $last_key) {
        // last element
    } else {
        // not last element
    }
}
Jeremy Ruten
quelle
2
+1 Ich stimme zu - die anderen Lösungen basieren auf dem Array mit numerischen Indizes.
Patrick Glandien
19
Zu meiner eigenen Verteidigung hängt meine Antwort nicht davon ab, dass das Array Zifferntasten hat :)
Richard Levasseur
2
Der Zeichenfolgenvergleich ist langsamer als Ganzzahlen und beim Vergleich von Zeichenfolgen mit Ganzzahlen nicht immer genau (Sie sollten mindestens === verwendet haben). Ich stimme ab.
OIS
4
Es ist elegant, verursacht aber STRICT NOTICE, da "end" einen Referenzwert erwartet :(
Wiliam
10
Fix für STRICT NOTICE:$lastKey = array_search(end($array), $array);
Ajax
44

warum so kompliziert?

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

Dies fügt hinter jedem Wert außer dem letzten einen Wert hinzu!

Trikks
quelle
2
Nicht, wenn die nächste $ -Eingabe den booleschen Wert false enthält, was bei next () ein großes Problem darstellt.
Soulseekah
29
Wenn ich mich nicht irre, funktioniert dies nicht, da der Aufruf von next () den Array-Zeiger vorschiebt, sodass Sie jedes andere Element in der Schleife überspringen.
Jordan Lev
2
Scheint bei mir nicht zu funktionieren. Das vorletzte Element erhält kein Komma, sollte es aber.
zuallauz
1
Wenn der Wert bool false entspricht, funktioniert er nicht. Gibt auch nicht das letzte Komma zwischen dem vorletzten und dem letzten Wert aus.
OIS
1
Ein Hinweis für alle, die dies in PHP7 verwenden möchten - der Array-Zeiger bewegt sich nicht in foreach-Schleifen, und dies funktioniert nicht.
Scott Flack
26

Wenn toEnd 0 erreicht, bedeutet dies, dass es sich um die letzte Iteration der Schleife handelt.

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

Der letzte Wert ist nach der Schleife noch verfügbar. Wenn Sie ihn also nach der Schleife nur für weitere Aufgaben verwenden möchten, ist dies besser:

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

Wenn Sie den letzten Wert nicht als spezielle Innenschleife behandeln möchten. Dies sollte schneller sein, wenn Sie große Arrays haben. (Wenn Sie das Array nach der Schleife innerhalb desselben Bereichs wiederverwenden, müssen Sie zuerst das Array "kopieren").

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

Und um Ihre ursprüngliche Frage zu beantworten "in meinem Fall Anhängen oder / und Parameter beim Erstellen der Abfrage"; Dadurch werden alle Werte durchlaufen und dann zu einer Zeichenfolge mit "und" zwischen ihnen zusammengefügt, jedoch nicht vor dem ersten Wert oder nach dem letzten Wert:

$params = [];
foreach ($array as $value) {
    $params[] = doSomething($value);
}
$parameters = implode(" and ", $params);
OIS
quelle
2
Natürlich wird es - $ toEnd für jede Iteration ausführen, das ist der Punkt. Wenn ich es außerhalb der Schleife verschieben würde, würde es nicht mehr funktionieren.
OIS
Die einfachste Methode, die jemals angewendet wurde. $lastValue = array_pop($array);Danke dir.
Elias Nicolas
21

Es gibt bereits viele Antworten, aber es lohnt sich auch, sich mit Iteratoren zu befassen, zumal nach einem Standardweg gefragt wurde:

$arr = range(1, 3);

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

Möglicherweise finden Sie etwas, das auch in anderen Fällen flexibler funktioniert.

hakre
quelle
Gute Antwort. Ich schätze, dass Sie die Funktionen der Sprache verwenden, die für die Aufgabe vorgesehen sind. i=0;und ++i;wirkten in einer Skriptsprache wie PHP immer hackisch.
CheddarMonkey
15

Eine Möglichkeit könnte darin bestehen, festzustellen, ob der Iterator dies getan hat next. Wenn dem Iterator kein nächster zugeordnet ist, bedeutet dies, dass Sie sich in der letzten Schleife befinden.

foreach ($some_array as $element) {
    if(!next($some_array)) {
         // This is the last $element
    }
}
Raheel
quelle
Ich denke, dass dies der einfachste Weg ist und die geringste Menge an Code erfordert!
Hallo, ich bin am
1
Funktioniert nicht mit PHP 7+ als "In PHP 7 verwendet foreach nicht den internen Array-Zeiger."
Damien Debin
8

Wenn Ihr Array also eindeutige Array-Werte hat, ist es trivial, die letzte Iteration zu bestimmen:

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

Wie Sie sehen, funktioniert dies, wenn das letzte Element nur einmal im Array erscheint, andernfalls erhalten Sie einen Fehlalarm. In diesem Fall müssen Sie nicht die Schlüssel vergleichen (die mit Sicherheit eindeutig sind).

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

Beachten Sie auch den strengen Coparision-Operator, der in diesem Fall sehr wichtig ist.

Rok Kralj
quelle
Das ist ziemlich ineffizient.
Ihr gesunder Menschenverstand
Nee. Es ist nicht. end () führt O (1) aus. Es ist auch kürzer als andere Lösungen und liest sich gut aus -> Wenn das Element dem Ende des Arrays entspricht, schreiben Sie "Last".
Rok Kralj
Dies ist mehr als doppelt so langsam wie mein erstes und letztes Beispiel für 100000 Werte.
OIS
5

Angenommen, Sie haben das Array in einer Variablen gespeichert ...

foreach($array as $key=>$value) 
{ 
    echo $value;
    if($key != count($array)-1) { echo ", "; }
}
Martin Heisterkamp
quelle
Dies ist sehr einfach und nützlich. Ich würde das Array nur zuerst außerhalb der foreach-Schleife zählen, damit das Programm nicht jedes Mal zählen muss, wenn die foreach-Funktion jedes Element auswertet.
Pathros
3
Dies funktioniert nicht bei assoziativen Arrays. $ key ist nicht immer eine Zahl.
Jonathan
5

um das erste und letzte Element aus jedem Array zu erhalten

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

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

Sie können diese Methode weiterhin mit assoziativen Arrays verwenden:

$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;
}
nickf
quelle
1
Bitte ändern Sie $ key = $ array [$ i]; zu $ key = $ keys [$ i]; in der ersten for-Schleife.
Narek
4

Wenn Sie für jedes Element etwas tun müssen, außer für das erste oder das letzte, und nur wenn das Array mehr als ein Element enthält, bevorzuge ich die folgende Lösung.

Ich weiß, dass es oben viele Lösungen gibt, die Monate / ein Jahr vor meinen veröffentlicht wurden, aber dies ist etwas, das ich für ziemlich elegant halte. Die Prüfung jeder Schleife ist auch eine boolesche Prüfung im Gegensatz zu einer numerischen Prüfung "i = (count-1)", die möglicherweise weniger Overhead ermöglicht.

Die Struktur der Schleife mag sich unangenehm anfühlen, aber Sie können sie mit der Reihenfolge von thead (Anfang), tfoot (Ende), tbody (aktuell) in HTML-Tabellen-Tags vergleichen.

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

Wenn Sie beispielsweise in Bezug auf die Webentwicklung jedem Element mit Ausnahme des letzten in einer ungeordneten Liste (ul) einen unteren Rand hinzufügen möchten, können Sie stattdessen jedem Element mit Ausnahme des ersten (CSS :) einen oberen Rand hinzufügen. Das erste Kind, das von IE7 + und Firefox / Webkit unterstützt wird, unterstützt diese Logik, während das letzte Kind von IE7 nicht unterstützt wird.

Sie können die Variable $ first auch für jede verschachtelte Schleife wiederverwenden, und die Dinge funktionieren einwandfrei, da jede Schleife $ first während des ersten Prozesses der ersten Iteration falsch macht (sodass Unterbrechungen / Ausnahmen keine Probleme verursachen). .

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

Beispielausgabe:

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)
Ankit Aggarwal
quelle
Danke, das ist meine Lieblingslösung! Es ist sehr flexibel und kostet nur einen Booleschen Wert. Übrigens denke ich, dass dies auch für Arrays funktioniert, die mindestens ein Element enthalten (nicht nur mehr als ein Element).
JC
4

Dies sollte der einfache Weg sein, um das letzte Element zu finden:

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

Referenz: Link

Dulitha Kumarasiri
quelle
- defekte Verbindung -
T30
3

Ich habe das starke Gefühl, dass das OP an der Wurzel dieses "XY-Problems" nur implode()funktionieren wollte .

Ihr gesunder Menschenverstand
quelle
1
wahr. Es gibt jedoch Fälle, in denen Implodieren nicht so praktisch ist. Stellen Sie sich zum Beispiel vor, Sie versuchen, eine lange HTML-Zeichenfolge mit vielen dynamischen Variablen zu implodieren. Sicher, Sie könnten ein ob_start / ob_get_clean darauf ausführen oder es einfach als $ str = '...' erstellen. Aber es gibt Zeiten, in denen dies nur als ein bisschen übertrieben angesehen werden kann
Alastair Brayne
3

Da Ihre Absicht, das EOF-Array zu finden, nur für den Kleber ist. Machen Sie sich mit der folgenden Taktik vertraut. Sie müssen den EOF nicht benötigen:

$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
Angelin Nadar
quelle
2

Es hört sich so an, als ob Sie so etwas wollen:

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

foreach($array as $key => $value)
{
    if(end($array) === $value)
    {
       echo "last index!" . $value;
    }
}
Ashique CM
quelle
2
Die Verwendung des Werts ist normalerweise keine gute Idee, da er nicht ordnungsgemäß funktioniert, wenn das Array zwei identische Werte aufweist.
7.
2

Fügen Sie nach dem letzten Wert kein Komma hinzu:

Das Array:

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

Die Funktion:

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

Das Ergebnis:

print $result;

Lorem, Ipsum, Dolor, sitzen, amet

Santo Boldižar
quelle
1

Sie können zählen ().

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

oder wenn Sie NUR das letzte Element suchen, können Sie end () verwenden.

end(arr);

gibt nur das letzte Element zurück.

und wie sich herausstellt, können Sie PHP-Arrays nach Ganzzahlen indizieren. Es ist vollkommen zufrieden mit

arr[1];
halloandre
quelle
1
Der Nachteil am Ende (arr) ist, dass der interne Zeiger des Arrays auf das letzte Element gesetzt wird.
Vijay
Nein, Sie sollten keine Ganzzahlen verwenden, um auf die Arrays zuzugreifen, es sei denn, Sie wissen, dass die Schlüssel numerisch und sequentiell sind. Bedenken Sie : $a = array(0=>'A', 2=>'B', 'aaa'=>'C'). Was bekommen Sie, wenn Sie darauf zugreifen $a[count($a)-1]?
Johndodo
1

Sie könnten auch so etwas tun:

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

     // more code
}
KOGI
quelle
end gibt den Wert zurück, nicht das Array. Die Art und Weise, wie Sie es erstellt haben, funktioniert also nicht. Der Zeichenfolgenvergleich ist auch langsamer als die Ganzzahl.
OIS
Du hast recht. es sollte end sein ($ elements); $ endKey = Schlüssel ($ Elemente);
KOGI
1

Ich mag das Folgende, da ich finde, dass es ziemlich ordentlich ist. Nehmen wir an, wir erstellen eine Zeichenfolge mit Trennzeichen zwischen allen Elementen: z. B. a, b, c

$first = true;
foreach ( $items as $item ) {
    $str = ($first)?$first=false:", ".$item;
}
Alastair Brayne
quelle
Machen Sie es einfacher, ohne zuerst $ zu deklarieren. Verwenden Sie foreach ($ items als $ key => $ item) und dann $ 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>";

}

Referenz

Ayman Elshehawy
quelle
0

Hier ist eine andere Möglichkeit, wie Sie es tun können:

$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);
    }
}
Kevin
quelle
0

Wenn ich Sie verstehe, müssen Sie nur das Array umkehren und das letzte Element mit einem Pop-Befehl abrufen:

   $rev_array = array_reverse($array);

   echo array_pop($rev_array);
James
quelle
0

Sie können dies auch versuchen, um Ihre Abfrage zu stellen ... hier mit INSERT angezeigt

<?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;
?>
Kennzeichen
quelle
0

Bei Skripten zur Generierung von SQL-Abfragen oder bei Skripten, die eine andere Aktion für das erste oder letzte Element ausführen, ist es viel schneller (fast doppelt so schnell), unnötige Variablenprüfungen zu vermeiden.

Die aktuell akzeptierte Lösung verwendet eine Schleife und eine Prüfung innerhalb der Schleife, die bei jeder einzelnen Wiederholung durchgeführt wird. Der richtige (schnelle) Weg, dies zu tun, ist der folgende:

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

Ein kleiner hausgemachter Benchmark zeigte Folgendes:

Test1: 100000 Läufe von Model Morg

Zeit: 1869.3430423737 Millisekunden

Test2: 100000 Modellläufe, wenn zuletzt

Zeit: 3235.6359958649 Millisekunden

Morg.
quelle
0

Ein anderer Weg besteht darin, sich das vorherige Ergebnis des Schleifenzyklus zu merken und dieses als Endergebnis zu verwenden:

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

Ich persönlich verwende diese Art von Konstruktion, die eine einfache Verwendung mit HTML-Elementen ul und ul ermöglicht: Ändern Sie einfach die Gleichheit für eine andere Eigenschaft ...

Das Array kann keine falschen Elemente enthalten, sondern alle anderen Elemente, die in den falschen Booleschen Wert umgewandelt werden.

$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;
}
MUY Belgien
quelle
0

Sie können den letzten Index direkt erhalten, indem Sie:

$numItems = count($arr);

echo $arr[$numItems-1];

Denis Omeri
quelle
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;?>
Zarpele
quelle
0

Hier ist meine Lösung: Ermitteln Sie einfach die Anzahl Ihres Arrays minus 1 (da sie bei 0 beginnen).

$lastkey = count($array) - 1;
foreach($array as $k=>$a){
    if($k==$lastkey){
        /*do something*/
    }
}
ITWitch
quelle