Heim - Internet-Setup
Foreach PHP-Wert des Folgenden. Führen Sie while- und foreach-Schleifen aus

Führen Sie while- und foreach-Schleifen aus

Schleife machen . . während

do...while-Schleife In C# ist dies eine Version von while mit einer Nachbedingungsprüfung. Dies bedeutet, dass die Schleifenbedingung überprüft wird, nachdem der Schleifenkörper ausgeführt wurde. Daher sind do...while-Schleifen in Situationen nützlich, in denen ein Anweisungsblock mindestens einmal ausgeführt werden muss. Das Folgende ist die allgemeine Form einer do-while-Schleifenanweisung:

do (Operatoren; ) while (Bedingung);

Wenn nur ein Operator vorhanden ist, sind geschweifte Klammern in dieser Notationsform optional. Sie werden jedoch häufig verwendet, um das Do-While-Konstrukt besser lesbar zu machen und nicht mit dem While-Schleifenkonstrukt zu verwechseln. Die do-while-Schleife läuft, solange der bedingte Ausdruck wahr ist. Ein Beispiel für die Verwendung einer Do-While-Schleife ist das folgende Programm, das die Fakultät einer Zahl berechnet:

Verwenden des Systems; mit System.Collections.Generic; mit System.Linq; Verwenden von System.Text; namespace ConsoleApplication1 ( class Program ( static void Main(string args) ( try ( // Berechnen Sie die Fakultät einer Zahl int i, result = 1, num = 1; Console.WriteLine("Geben Sie eine Zahl ein:"); i = int .Parse(Console .ReadLine()); Console.Write("\n\nFactorial (0) = ", i); do ( result *= num; num++; ) while (num

foreach-Schleife

foreach-Schleife dient dem zyklischen Zugriff auf Elemente einer Sammlung, also einer Gruppe von Objekten. C# definiert mehrere Arten von Sammlungen, von denen jede ein Array ist. Das Folgende ist die allgemeine Form der foreach-Schleifenanweisung:

foreach-Anweisung (Schleifenvariablenname in Sammlung eingeben);

Hier Geben Sie Schleifenvariablenname ein bezeichnet den Typ und Namen der Schleifenkontrollvariablen, die bei jedem Schritt der foreach-Schleife den Wert des nächsten Elements der Sammlung empfängt. Und Sammlung bezeichnet eine zyklisch abgefragte Sammlung, die im Folgenden ein Array darstellt. Daher muss der Typ der Schleifenvariablen mit dem Typ des Array-Elements übereinstimmen. Darüber hinaus kann ein Typ durch das Schlüsselwort var bezeichnet werden. In diesem Fall bestimmt der Compiler den Typ der Schleifenvariablen anhand des Typs des Array-Elements. Dies kann für die Arbeit mit bestimmten Arten von Abfragen nützlich sein. In der Regel wird der Typ jedoch explizit angegeben.

Die foreach-Schleifenanweisung funktioniert wie folgt. Wenn die Schleife startet, wird das erste Element des Arrays ausgewählt und der Schleifenvariablen zugewiesen. Bei jedem weiteren Iterationsschritt wird das nächste Array-Element ausgewählt und in einer Schleifenvariablen gespeichert. Die Schleife endet, wenn alle Elemente des Arrays ausgewählt sind.

Mit einer foreach-Schleife können Sie jedes Element einer Sammlung (ein Objekt, das eine Liste anderer Objekte darstellt) durchlaufen. Damit etwas technisch gesehen als Sammlung betrachtet werden kann, muss es die IEnumerable-Schnittstelle unterstützen. Beispiele für Sammlungen sind C#-Arrays, Sammlungsklassen aus dem System.Collection-Namespace und benutzerdefinierte Sammlungsklassen.

Die For Each...Next-Schleife in VBA Excel, ihre Syntax und Beschreibung der einzelnen Komponenten. Beispiele für die Verwendung der For Each...Next-Schleife.

Die For Each... Next-Schleife in VBA Excel dient dazu, einen Anweisungsblock in Bezug auf jedes Element aus einer Gruppe von Elementen (Bereich, Array, Sammlung) auszuführen. Diese wunderbare Schleife wird verwendet, wenn die Anzahl der Elemente in einer Gruppe und ihre Indizierung unbekannt sind, andernfalls wird .

For Each...Next-Schleifensyntax

Für jedes Element In der Gruppe [Anweisungen] [Beenden für] [Anweisungen] Nächstes [Element]

Die eckigen Klammern geben optionale Attribute der For Each...Next-Schleife an.

Komponenten einer For Each... Next-Schleife

*Wenn in VBA Excel eine For Each...Next-Schleife verwendet wird, um die Elemente einer Sammlung (Sammlungsobjekt) oder eines Arrays zu durchlaufen, dann die Variable Element muss mit einem Datentyp deklariert werden Variante, sonst funktioniert die Schleife nicht.

**Wenn Sie in einer Schleife keinen eigenen Code verwenden, geht die Bedeutung der Verwendung einer Schleife verloren.

Beispiele für For Each...Next-Schleifen

Schleife über einen Bereich von Zellen

Wählen Sie im aktiven Blatt der Excel-Arbeitsmappe einen Zellbereich aus und führen Sie das folgende Verfahren aus:

Sub test1() Dim element As Range, a As String a = „Daten erhalten von For Each... Next:“ For Each element In Selection a = a & vbNewLine & „Cell“ & element.Address & _ „enthält den Wert : " & CStr(element.Value) Next MsgBox a End Sub

Das MsgBox-Informationsfenster zeigt die Adressen der ausgewählten Zellen und ggf. deren Inhalte an. Wenn viele Zellen ausgewählt sind, werden keine vollständigen Informationen zu allen Zellen angezeigt, da die maximale Länge des Parameters erreicht ist Prompt beträgt ca. 1024 Zeichen.

Schleife für eine Sammlung von Blättern

Kopieren Sie die folgende VBA-Prozedur in Excel-Arbeitsmappen:

Sub test2() Dim element As Worksheet, a As String a = "Liste der in diesem Arbeitsblatt enthaltenen Blätter:" Für jedes Element in Arbeitsblättern a = a & vbNewLine & element.Index _ & ") " & element.Name Next MsgBox a Sub beenden

Das MsgBox-Informationsfenster zeigt eine Liste der Namen aller Blätter in der Excel-Arbeitsmappe nach der Seriennummer ihrer Beschriftungen an, die ihren Indizes entsprechen.

Schleife für ein Array

Weisen wir dem Array eine Liste mit Tiernamen zu und schreiben sie in eine Variable in der For Each... Next-Schleife A. Das MsgBox-Informationsfenster zeigt eine Liste der Tiernamen aus der Variablen an A.

Sub test3() Dim element As Variant, a As String, group As Variant group = Array("hippopotamus", "elephant", "kangaroo", "tiger", "mouse") "oder Sie können die Werte von zuweisen Der Zellbereich des „Workers“ zum Array-Blatt wird beispielsweise ausgewählt: Gruppe = Auswahl a = „Das Array enthält die folgenden Werte:“ & vbNewLine Für jedes Element In Gruppe a = a & vbNewLine & Element Nächste MsgBox a Sub beenden

Wiederholen wir die gleiche VBA-Prozedur, weisen jedoch allen Array-Elementen in der For Each...Next-Schleife den Wert „Parrot“ zu. Das MsgBox-Informationsfenster zeigt eine Liste mit Tiernamen an, die nur aus Papageien besteht, was beweist, dass es möglich ist, die Werte von Array-Elementen in der For Each...Next-Schleife zu bearbeiten.

Sub test4() Dim element As Variant, a As String, group As Variant group = Array("hippopotamus", "elephant", "kangaroo", "tiger", "mouse") "oder Sie können die Werte von zuweisen der Zellbereich des „Arbeiters“ zum Array-Blatt, zum Beispiel das ausgewählte: group = Selection a = „Das Array enthält die folgenden Werte:“ & vbNewLine Für jedes Element in der Gruppe element = „Parrot“ a = a & vbNewLine & element Next MsgBox a End Sub

Dieser Code wurde, wie alle anderen in diesem Artikel, in Excel 2016 getestet.

Durchlaufen Sie eine Sammlung von Unterverzeichnissen und verlassen Sie die Schleife

In diesem Beispiel werden wir die Variable ergänzen A Namen von Unterverzeichnissen auf der Festplatte C Ihrem Computer. Wenn die Schleife den Ordner erreicht Programmdateien, es wird zur Variablen hinzugefügt A Titel und Botschaft: „Genug, ich lese nicht weiter!“ Mit freundlichen Grüßen, Ihr Für Jeden...Nächsten Zyklus.“

Sub test5() Dim FSO As Object, myFolders As Object, myFolder As Object, a As String „Erstellen Sie ein neues FileSystemObject und weisen Sie es der Variablen „FSO“ zu. Set FSO = CreateObject(“Scripting.FileSystemObject“) „Rufen Sie die Liste von ab Unterverzeichnisse auf Laufwerk „C“ „ und weisen Sie es der Variablen „myFolders“ zu. Set myFolders = FSO.GetFolder(“C:\“) a = „Ordner auf Laufwerk C:“ & vbNewLine „Wir durchlaufen die Liste der Unterverzeichnisse und Fügen Sie ihre Namen zur Variablen „a“ hinzu. Nachdem wir den Ordner „Programme“ erreicht haben, verlassen wir den Zyklus. Für jeden myFolder in myFolders.SubFolders a = a & vbNewLine & myFolder.Name If myFolder.Name = „Program Files“ Then a = a & vbNewLine & vbNewLine & „Das reicht, ich werde nicht weiterlesen!“ _ & vbNewLine & vbNewLine & „Grüße“, & vbNewLine & _ „Ihre Schleife ist For Each... Next.“ FSO = Nothing MsgBox a End Sub

Das MsgBox-Informationsfenster zeigt eine Liste der Unterverzeichnisnamen auf der Festplatte an C von Ihrem Computer in den Ordner Programmdateien inklusive und eine Nachricht aus dem Zyklus über die Beendigung seiner Arbeit.

Aufgrund der Programmausführung werden nicht nur die Namen der Unterverzeichnisse angezeigt, die beim Navigieren zur Festplatte im Explorer sichtbar sind C, aber auch versteckte und Service-Ordner. Um eine Liste aller Unterverzeichnisse auf einem Datenträger anzuzeigen C, kommentieren Sie den Codeabschnitt aus Wenn Zu Ende wenn inklusive und führen Sie die Prozedur im VBA-Excel-Editor aus.

Oft müssen Sie alle Elemente eines PHP-Arrays durchlaufen und für jedes Element eine Operation ausführen. Sie können beispielsweise jeden Wert in eine HTML-Tabelle ausgeben oder jedem Element einen neuen Wert zuweisen.

In dieser Lektion betrachten wir das foreach-Konstrukt beim Organisieren einer Schleife über indizierte und zugehörige Arrays.

Elementwerte durchlaufen

Der einfachste Anwendungsfall für foreach besteht darin, Werte in einem indizierten Array zu durchlaufen. Grundlegende Syntax:

Foreach ($array as $value) ( ​​​​// Etwas mit $value machen) // Hier wird der Code ausgeführt, nachdem die Schleife abgeschlossen ist

Das folgende Skript durchläuft beispielsweise die Liste der Direktoren in einem indizierten Array und gibt den Namen jedes einzelnen aus:

$directors = array("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); foreach ($directors as $director) ( echo $director . "
"; }

Der obige Code gibt Folgendes aus:

Alfred Hitchcock, Stanley Kubrick, Martin Scorsese, Fritz Lang

Schlüsselwertschleife

Was ist mit zugehörigen Arrays? Wenn Sie diesen Array-Typ verwenden, benötigen Sie häufig Zugriff auf den Schlüssel jedes Elements sowie auf seinen Wert. Das foreach-Konstrukt bietet eine Möglichkeit, das Problem zu lösen:

Foreach ($array as $key => $value) ( ​​​​// Etwas mit $key und/oder $value machen) // Hier wird der Code ausgeführt, nachdem die Schleife abgeschlossen ist

Ein Beispiel für die Organisation einer Schleife durch ein zugehöriges Array mit Informationen zu Filmen, wobei der Schlüssel jedes Elements und sein Wert in der HTML-Definitionsliste angezeigt werden:

$movie = array("title" => "Rear Window", "director" => "Alfred Hitchcock", "year" => 1954, "minutes" => 112); Echo“

"; foreach ($movie as $key => $value) ( ​​​​echo "
$key:
"; Echo "
$Wert
„; ) Echo“
";

Bei der Ausführung gibt dieses Skript Folgendes aus:

Titel: Rear Window Regie: Alfred Hitchcock Jahr: 1954 Minuten: 112

Den Wert eines Elements ändern

Wie wäre es, den Wert eines Elements zu ändern, während die Schleife durchlaufen wird? Sie können diesen Code ausprobieren:

Foreach ($myArray as $value) ( ​​​​$value = 123; )

Wenn Sie es jedoch ausführen, werden Sie feststellen, dass die Werte im Array vorhanden sind nicht ändern. Der Grund dafür ist, dass foreach mit funktioniert eine Kopie Array-Werte, nicht mit dem Original. Auf diese Weise bleibt das ursprüngliche Array erhalten.

Um Array-Werte zu ändern, benötigen Sie Link zur Bedeutung. Dazu müssen Sie im foreach-Konstrukt ein &-Zeichen vor die Wertvariable setzen:

Foreach ($myArray as &$value) ( ​​​​$value = 123; )

Das folgende Skript durchläuft beispielsweise jedes Element (Name des Direktors) im Array $directors und verwendet die PHP-Funktion explosion() und das Listenkonstrukt, um den Vor- und Nachnamen umzukehren:

$directors = array("Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang"); // Ändern Sie das Namensformat für jedes Element foreach ($directors as &$director) ( list($firstName, $lastName) = explosion(" ", $director); $director = "$lastName, $firstName"; ) unset ( $director); // Das Endergebnis ausgeben foreach ($directors as $director) ( echo $director . "
"; }

Das Skript gibt Folgendes aus:

Hitchcock, Alfred Kubrick, Stanley Scorsese, Martin Lang, Fritz

Beachten Sie, dass das Skript die Funktion unset() aufruft, um die Variable $director zu entfernen, nachdem die erste Schleife abgeschlossen ist. Dies empfiehlt sich, wenn Sie die Variable später im Skript in einem anderen Kontext verwenden möchten.

Wenn Sie die Referenz nicht entfernen, besteht die Gefahr, dass bei weiterer Codeausführung versehentlich auf das letzte Element im Array („Lang, Fritz“) verwiesen wird, wenn Sie die Variable $director weiterhin verwenden, was zu unbeabsichtigten Konsequenzen führt!

Wieder aufnehmen

In diesem Tutorial haben wir uns angeschaut, wie man das PHP-Foreach-Konstrukt verwendet, um die Elemente eines Arrays zu durchlaufen. Folgende Themen wurden berücksichtigt:

  • So durchlaufen Sie Array-Elemente
  • So greifen Sie auf den Schlüssel und den Wert jedes Elements zu
  • So verwenden Sie eine Referenz, um Werte zu ändern, während Sie eine Schleife durchlaufen

In einer aktuellen Zusammenfassung interessanter Links zu PHP habe ich einen Link zu einem Kommentar von Nikita Popov auf StackOverflow gefunden, in dem er ausführlich über den Mechanismus „unter der Haube“ des foreach-Kontrollkonstrukts spricht.
Da foreach manchmal auf mehr als seltsame Weise funktioniert, dachte ich, es wäre nützlich, diese Antwort zu übersetzen.

Achtung: Dieser Text setzt Grundkenntnisse der Funktionalität von zvals in PHP voraus, insbesondere sollten Sie wissen, was refcount und is_ref sind.
foreach funktioniert mit Entitäten verschiedener Typen: mit Arrays, mit einfachen Objekten (wo verfügbare Eigenschaften aufgelistet sind) und mit durchquerbaren Objekten (oder besser gesagt Objekten, für die ein interner get_iterator-Handler definiert ist). Wir sprechen hier hauptsächlich über Arrays, aber über den Rest werde ich ganz zum Schluss sprechen.

Bevor wir beginnen, ein paar Worte zu Arrays und ihrer Durchquerung, die für das Verständnis des Kontexts wichtig sind.

Wie funktioniert Array-Traversal?

Arrays in PHP sind geordnete Hash-Tabellen (die Hash-Elemente werden zu einer doppelt verknüpften Liste zusammengefasst) und foreach durchläuft das Array in der angegebenen Reihenfolge.

PHP bietet zwei Möglichkeiten, ein Array zu durchlaufen:

  • Der erste Weg ist ein interner Array-Zeiger. Dieser Zeiger ist Teil der HashTable-Struktur und lediglich ein Zeiger auf das aktuelle Hash-Tabellenelement. Der interne Array-Zeiger kann ungestraft geändert werden, d. h. wenn das aktuelle Element gelöscht wird, wird der interne Array-Zeiger auf das nächste verschoben.
  • Der zweite Iterationsmechanismus ist ein externer Array-Zeiger namens HashPosition. Dies entspricht im Wesentlichen einem internen Array-Zeiger, ist jedoch nicht Teil der HashTable. Diese externe Art der Iteration ist nicht änderungssicher. Wenn Sie das Element entfernen, auf das HashPosition zeigt, bleibt ein hängender Zeiger zurück, der zu einem Segmentierungsfehler führt.

Daher sollten externe Array-Zeiger nur verwendet werden, wenn Sie absolut sicher sind, dass während des Durchlaufs kein Benutzercode ausgeführt wird. Und solcher Code kann an den unerwartetsten Stellen landen, beispielsweise in einem Fehlerhandler oder einem Destruktor. Aus diesem Grund muss PHP in den meisten Fällen einen internen Zeiger anstelle eines externen verwenden. Andernfalls könnte PHP mit einem Segmentierungsfehler abstürzen, sobald der Benutzer etwas Ungewöhnliches tut.

Das Problem mit dem internen Zeiger besteht darin, dass er Teil der HashTable ist. Wenn Sie es also ändern, ändert sich auch die HashTable. Und da auf Arrays in PHP über den Wert zugegriffen wird (und nicht über die Referenz), sind Sie gezwungen, das Array zu kopieren, um seine Elemente in einer Schleife zu durchlaufen.

Ein einfaches Beispiel, das die Bedeutung des Kopierens zeigt (übrigens nicht so ungewöhnlich), ist die verschachtelte Iteration:

Foreach ($array as $a) ( foreach ($array as $b) ( // ... ) )

Hier möchten Sie, dass beide Schleifen unabhängig sind und nicht geschickt mit einem Zeiger herumgeworfen werden.

Also kommen wir zu foreach.

Durchlaufen eines Arrays in foreach

Jetzt wissen Sie, warum foreach eine Kopie des Arrays erstellen muss, bevor es es durchlaufen kann. Aber das ist offensichtlich nicht die ganze Geschichte. Ob PHP eine Kopie erstellt oder nicht, hängt von mehreren Faktoren ab:

  • Wenn das iterierbare Array eine Referenz ist, erfolgt kein Kopieren, stattdessen wird addref ausgeführt:

    $ref =& $array; // $array hat is_ref=1 jetzt foreach ($array as $val) ( // ... )
    Warum? Denn jede Änderung am Array muss per Referenz weitergegeben werden, einschließlich des internen Zeigers. Wenn foreach in diesem Fall eine Kopie erstellen würde, würde dies die Semantik des Links zerstören.

  • Wenn das Array refcount=1 hat, wird das Kopieren erneut nicht durchgeführt. refcount=1 bedeutet, dass das Array nicht anderswo verwendet wird und foreach es direkt verwenden kann. Wenn refcount größer als eins ist, wird das Array mit anderen Variablen geteilt und um Änderungen zu vermeiden, muss foreach es kopieren (unabhängig vom oben beschriebenen Referenzfall).
  • Wenn das Array referenziert wird (foreach ($array as &$ref)), wird das Array – unabhängig von der Kopier- oder Nicht-Kopierfunktion – zu einer Referenz.

Das ist also der erste Teil des Rätsels: die Kopierfunktion. Der zweite Teil ist die Art und Weise, wie die aktuelle Iteration ausgeführt wird, und er ist auch ziemlich seltsam. Das „normale“ Iterationsmuster, das Sie bereits kennen (und das in PHP häufig verwendet wird – getrennt von foreach) sieht in etwa so aus (Pseudocode):

Zurücksetzen(); while (get_current_data(&data) == SUCCESS) ( code(); move_forward(); )
Die foreach-Iteration sieht etwas anders aus:

Zurücksetzen(); while (get_current_data(&data) == SUCCESS) ( move_forward(); code(); )

Der Unterschied besteht darin, dass move_forward() am Anfang und nicht am Ende der Schleife ausgeführt wird. Wenn Benutzercode also das Element $i verwendet, zeigt der interne Array-Zeiger bereits auf das Element $i+1.

Diese Funktionsweise von foreach ist auch der Grund dafür, dass der interne Array-Zeiger zum nächsten Element wechselt, wenn das aktuelle gelöscht wird, und nicht zum vorherigen (wie zu erwarten). Alles ist so konzipiert, dass es gut mit foreach funktioniert (funktioniert aber offensichtlich nicht so gut mit allem anderen, da Elemente übersprungen werden).

Code-Auswirkungen

Die erste Konsequenz des obigen Verhaltens besteht darin, dass foreach in vielen Fällen (langsam) das iterierbare Array kopiert. Aber keine Angst: Ich habe versucht, die Kopieranforderung zu entfernen, konnte jedoch nirgendwo eine Beschleunigung feststellen, außer bei den künstlichen Benchmarks (die doppelt so schnell iterierten). Es scheint, als ob die Leute einfach nicht genug iterieren.

Die zweite Konsequenz ist, dass es in der Regel keine weiteren Konsequenzen geben sollte. Das Verhalten von foreach ist für den Benutzer im Allgemeinen recht verständlich und funktioniert genau so, wie es sollte. Es sollte Ihnen egal sein, wie das Kopieren erfolgt (oder ob es überhaupt erfolgt) oder zu welchem ​​Zeitpunkt der Zeiger bewegt wird.

Und die dritte Konsequenz – und hier kommen wir zu Ihrem Problem – ist, dass wir manchmal sehr seltsame Verhaltensweisen beobachten, die schwer zu verstehen sind. Dies geschieht insbesondere dann, wenn Sie versuchen, das Array selbst zu ändern, das Sie in einer Schleife durchlaufen.

Eine große Sammlung von Randfallverhalten, das auftritt, wenn Sie ein Array während der Iteration ändern, finden Sie in PHP-Tests. Sie können mit diesem Test beginnen, dann in der Adresse 012 in 013 ändern und so weiter. Sie werden sehen, wie sich das foreach-Verhalten in verschiedenen Situationen manifestiert (alle möglichen Kombinationen von Links usw.).

Kommen wir nun zurück zu Ihren Beispielen:

Foreach ($array as $item) ( echo "$item\n"; $array = $item; ) print_r($array); /* Ausgabe in Schleife: 1 2 3 4 5 $array nach Schleife: 1 2 3 4 5 1 2 3 4 5 */

Hier hat $array vor der Schleife refcount=1, sodass es nicht kopiert wird, sondern addref erhält. Sobald Sie $array einen Wert zuweisen, wird der zval aufgeteilt, sodass das Array, dem Sie Elemente hinzufügen, und das Array, auf dem Sie iterieren, zwei verschiedene Arrays sind.

Foreach ($array as $key => $item) ( $array[$key + 1] = $item + 2; echo "$item\n"; ) print_r($array); /* Ausgabe in Schleife: 1 2 3 4 5 $array nach Schleife: 1 3 4 5 6 7 */

Die gleiche Situation wie im ersten Test.

// Den Zeiger um eins verschieben, um sicherzustellen, dass er keine Auswirkungen auf foreach hat var_dump(each($array)); foreach ($array as $item) ( echo "$item\n"; ) var_dump(each($array)); /* Ausgabearray(4) ( => int(1) ["value"]=> int(1) => int(0) ["key"]=> int(0) ) 1 2 3 4 5 bool( FALSCH) */

Wieder die gleiche Geschichte. Während der foreach-Schleife haben Sie refcount=1 und erhalten nur addref, der interne $array-Zeiger wird geändert. Am Ende der Schleife wird der Zeiger NULL (das bedeutet, dass die Iteration abgeschlossen ist). Jeder demonstriert dies, indem er false zurückgibt.

Foreach ($array as $key => $item) ( echo "$item\n"; every($array); ) /* Ausgabe: 1 2 3 4 5 */

Foreach ($array as $key => $item) ( echo "$item\n"; reset($array); ) /* Ausgabe: 1 2 3 4 5 */

Aber diese Beispiele sind nicht überzeugend genug. Das Verhalten wird wirklich unvorhersehbar, wenn Sie Strom in einer Schleife verwenden:

Foreach ($array as $val) ( var_dump(current($array)); ) /* Ausgabe: 2 2 2 2 2 */

Dabei ist zu beachten, dass auf current auch per Referenz zugegriffen wird, auch wenn das Array nicht verändert wird. Dies ist erforderlich, um konsistent mit allen anderen Funktionen wie next zu arbeiten, die per Referenz zugreifen (current ist eigentlich eine bevorzugte Referenzfunktion; sie kann einen Wert abrufen, verwendet aber, wenn möglich, eine Referenz). Eine Referenz bedeutet, dass das Array getrennt sein muss, sodass $array und die von foreach verwendete Kopie von $array unabhängig sind. Warum Sie 2 und nicht 1 erhalten, wird ebenfalls oben erwähnt: foreach erhöht den Array-Zeiger vor Beginn des Benutzercodes, nicht danach. Selbst wenn der Code also noch am ersten Element arbeitet, hat foreach den Zeiger bereits auf das zweite verschoben.

Versuchen wir nun eine kleine Änderung:

$ref = &$array; foreach ($array as $val) ( var_dump(current($array)); ) /* Ausgabe: 2 3 4 5 false */

Hier haben wir is_ref=1, also wird das Array nicht kopiert (wie oben). Aber jetzt, da es is_ref gibt, muss das Array nicht mehr geteilt werden, sondern wird als Referenz an current übergeben. Jetzt arbeiten current und foreach mit demselben Array. Sie sehen, dass das Array genau aufgrund der Art und Weise, wie foreach den Zeiger behandelt, um eins verschoben ist.

Das Gleiche sehen Sie, wenn Sie ein Array per Referenz durchlaufen:

Foreach ($array as &$val) ( var_dump(current($array)); ) /* Ausgabe: 2 3 4 5 false */

Das Wichtige hier ist, dass foreach unserem $array is_ref=1 zuweist, wenn es als Referenz darüber läuft, sodass es am Ende das Gleiche wie oben ergibt.

Eine weitere kleine Variante, hier werden wir unser Array einer anderen Variablen zuweisen:

$foo = $array; foreach ($array as $val) ( var_dump(current($array)); ) /* Ausgabe: 1 1 1 1 1 */

Hier ist der Refcount von $array beim Start der Schleife auf 2 gesetzt, sodass vor dem Start eine Kopie erstellt werden muss. Daher unterscheiden sich $array und das von foreach verwendete Array von Anfang an. Deshalb erhalten Sie die Position des internen Array-Zeigers, die vor Beginn der Schleife relevant war (in diesem Fall an der ersten Position).

Iteration von Objekten

Bei der Iteration von Objekten ist es sinnvoll, zwei Fälle zu berücksichtigen:

Das Objekt ist nicht durchlaufbar (bzw. der interne get_iterator-Handler ist nicht definiert)

In diesem Fall erfolgt die Iteration fast genauso wie bei Arrays. Die gleiche Semantik des Kopierens. Der einzige Unterschied besteht darin, dass foreach zusätzlichen Code ausführt, um Eigenschaften zu überspringen, die im aktuellen Bereich nicht verfügbar sind. Noch ein paar interessante Fakten:

  • Für deklarierte Eigenschaften optimiert PHP die Eigenschafts-Hash-Tabelle erneut. Wenn Sie das Objekt iterieren, muss es diese Hash-Tabelle neu erstellen (was die Speichernutzung erhöht). Sie sollten sich darüber keine Sorgen machen, seien Sie sich nur bewusst.
  • Bei jeder Iteration wird die Eigenschaften-Hash-Tabelle neu abgerufen, was bedeutet, dass PHP get_properties immer wieder aufruft. Für „normale“ Eigenschaften ist dies nicht so wichtig, aber wenn Eigenschaften dynamisch erstellt werden (dies geschieht häufig durch integrierte Klassen), wird die Eigenschaftentabelle jedes Mal neu berechnet.
Durchquerbares Objekt

In diesem Fall gilt das oben Gesagte in keiner Weise. Außerdem kopiert PHP nicht und verwendet keine Tricks wie das Erhöhen des Zeigers vor der Schleife. Ich denke, dass die Art und Weise, wie ein durchquerbares Objekt durchlaufen wird, viel vorhersehbarer ist und keiner weiteren Beschreibung bedarf.

Ersetzen eines Iterables während einer Schleife

Ein weiterer ungewöhnlicher Fall, den ich nicht erwähnt habe, ist, dass PHP die Möglichkeit bietet, ein Iterable während einer Schleife zu ersetzen. Sie können mit einem Array beginnen und nach der Hälfte der Arbeit fortfahren, indem Sie es durch ein anderes ersetzen. Oder beginnen Sie mit einem Array und ersetzen Sie es dann durch ein Objekt:

$arr = ; $obj = (Objekt) ; $ref =& $arr; foreach ($ref as $val) ( echo "$val\n"; if ($val == 3) ( $ref = $obj; ) ) /* Ausgabe: 1 2 3 6 7 8 9 10 */

Wie Sie sehen können, hat PHP sofort nach der Ersetzung damit begonnen, die andere Entität zu durchlaufen.

Ändern des internen Array-Zeigers während der Iteration

Ein letztes Detail des foreach-Verhaltens, das ich nicht erwähnt habe (weil es zum Abrufen verwendet werden kann wirklich seltsames Verhalten): Was kann passieren, wenn Sie versuchen, den internen Array-Zeiger während einer Schleife zu ändern?

Hier erhalten Sie möglicherweise nicht das, was Sie erwartet haben: Wenn Sie next oder prev im Schleifenkörper aufrufen (im Fall der Referenzübergabe), werden Sie sehen, dass sich der interne Zeiger bewegt hat, dies hat jedoch keine Auswirkungen auf das Verhalten von der Iterator. Der Grund dafür ist, dass foreach nach jedem Durchlauf der Schleife eine Sicherung der aktuellen Position und des Hashs des aktuellen Elements im HashPointer erstellt. Beim nächsten Durchgang prüft foreach, ob sich die Position des internen Zeigers geändert hat, und versucht, ihn mithilfe dieses Hashs wiederherzustellen.

Mal sehen, was „wird versuchen“ bedeutet. Das erste Beispiel zeigt, dass eine Änderung des internen Zeigers den foreach-Modus nicht ändert:

$array = ; $ref =& $array; foreach ($array as $value) ( ​​​​var_dump($value); reset($array); ) // Ausgabe: 1, 2, 3, 4, 5

Versuchen wir nun, das Element zu deaktivieren, auf das foreach beim ersten Durchgang zugreift (Schlüssel 1):

$array = ; $ref =& $array; foreach ($array as $value) ( ​​​​var_dump($value); unset($array); reset($array); ) // Ausgabe: 1, 1, 3, 4, 5

Hier sehen Sie, dass der Zähler zurückgesetzt wurde, da kein Element mit passendem Hash gefunden werden konnte.

Denken Sie daran, ein Hash ist nur ein Hash. Es kommt zu Kollisionen. Versuchen wir es jetzt:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $array; foreach ($array as $value) ( ​​​​unset($array["EzFY"]); $array["FYFZ"] = 4; reset($array); var_dump($value); ) // Ausgabe: 1 1 3 4

Funktioniert wie erwartet. Wir haben den EzFY-Schlüssel (den Schlüssel, in dem sich foreach befand) entfernt, sodass ein Reset durchgeführt wurde. Wir haben auch einen zusätzlichen Schlüssel hinzugefügt, sodass wir am Ende 4 sehen.

Und hier kommt das Unbekannte. Was passiert, wenn Sie den FYFY-Schlüssel durch FYFZ ersetzen? Versuchen wir es:

$array = ["EzEz" => 1, "EzFY" => 2, "FYEz" => 3]; $ref =& $array; foreach ($array as $value) ( ​​​​unset($array["EzFY"]); $array["FYFY"] = 4; reset($array); var_dump($value); ) // Ausgabe: 1 4

Jetzt ist die Schleife direkt zum neuen Element verschoben und überspringt alles andere. Dies liegt daran, dass der FYFY-Schlüssel eine Kollision mit EzFY hat (eigentlich auch alle Schlüssel aus diesem Array). Darüber hinaus befindet sich das FYFY-Element an derselben Speicheradresse wie das gerade gelöschte EzFY-Element. Für PHP ist es also dieselbe Position mit demselben Hash. Die Position wird „wiederhergestellt“ und der Übergang zum Ende des Arrays erfolgt.

Das foreach-Konstrukt ist eine Variation von for, die in der Sprache enthalten ist, um das Durchlaufen der Elemente eines Arrays zu erleichtern. Es gibt zwei Varianten des foreach-Befehls, die für unterschiedliche Array-Typen konzipiert sind:

foreach (Array als $element) (

foreach (Array als $key => $element) (

Beispielsweise beim Ausführen des folgenden Snippets:

$menu = array("Pasta", "Steak", "Kartoffeln", "Fisch", "Pommes");

foreach ($menu als $item) (

Drucken Sie „$item
";

Folgendes Ergebnis wird ausgegeben:

In diesem Beispiel sind zwei Dinge zu beachten. Erstens kehrt das foreach-Konstrukt automatisch zum Anfang des Arrays zurück (dies geschieht bei anderen Schleifenkonstrukten nicht). Zweitens besteht keine Notwendigkeit, den Zähler explizit zu erhöhen oder auf andere Weise zum nächsten Element des Arrays zu wechseln – dies geschieht automatisch bei jeder Iteration von foreach.

Die zweite Option wird beim Arbeiten mit assoziativen Arrays verwendet:

$wine_inventory = Array (

"Merlot" => 15,

"Zinfandel" => 17,

"sauvignon" => 32

foreach ($wine_inventory as $i => $item_count) (

print „$item_count verbleibende Flaschen von $i
";

In diesem Fall sieht das Ergebnis so aus:

Es sind noch 15 Flaschen Merlot übrig

Es sind noch 17 Flaschen Zinfandel übrig

Es sind noch 32 Flaschen Sauvignon übrig

Wie Sie anhand der obigen Beispiele sehen können, vereinfacht das foreach-Konstrukt die Arbeit mit Arrays erheblich.

Das Funktionsprinzip des Schalterkonstrukts erinnert ein wenig an if – das Ergebnis der Auswertung des Ausdrucks wird mit einer Liste potenzieller Übereinstimmungen verglichen.

Dies ist besonders nützlich, wenn mehrere Werte überprüft werden, da die Verwendung eines Schalters das Programm visueller und kompakter macht. Das allgemeine Format des Switch-Befehls ist:

Schalter (Ausdruck) (

Fall (Bedingung):

Fall (Bedingung):

Die getestete Bedingung wird in Klammern nach dem Schlüsselwort switch angegeben. Das Ergebnis seiner Berechnung wird sequentiell mit den Bedingungen in den Fallabschnitten verglichen. Wird eine Übereinstimmung gefunden, wird der Block des entsprechenden Abschnitts ausgeführt. Wenn keine Übereinstimmung gefunden wird, wird der optionale Standardabschnittsblock ausgeführt.

Wie Sie in späteren Kapiteln sehen werden, ist die Verarbeitung von Benutzereingaben eine der größten Stärken von PHP. Nehmen wir an, ein Programm zeigt eine Dropdown-Liste mit mehreren Optionen an und jede Zeile in der Liste entspricht einem Befehl, der in einem separaten Fallkonstrukt ausgeführt wird. Es ist sehr praktisch, die Implementierung mit dem Befehl switch zu erstellen:

$user_input = "Rezepte"; // Vom Benutzer ausgewählter Befehl

Schalter ($user_input):

case("search") :

print „Lass uns eine Suche durchführen!“;

case("Wörterbuch") :

print „Welches Wort möchten Sie nachschlagen?“;

case("Rezepte") :

print „Hier ist eine Liste mit Rezepten …“;

print „Hier ist das Menü...“;

Wie Sie dem obigen Fragment entnehmen können, sorgt der Switch-Befehl für eine klare und visuelle Organisation des Codes. Die in der Schalterbedingung angegebene Variable (in diesem Beispiel $user_input) wird mit den Bedingungen aller nachfolgenden Fallabschnitte verglichen. Wenn der im Case-Abschnitt angegebene Wert mit dem Wert der verglichenen Variablen übereinstimmt, wird der Block dieses Abschnitts ausgeführt. Der Befehl break verhindert die Prüfung weiterer Case-Abschnitte und beendet die Ausführung des Switch-Konstrukts. Wenn keine der geprüften Bedingungen erfüllt ist, wird der optionale Standardabschnitt aktiviert. Wenn kein Standardabschnitt vorhanden ist und keine der Bedingungen erfüllt ist, wird der Umschaltbefehl einfach beendet und die Programmausführung mit dem nächsten Befehl fortgesetzt.

Sie müssen bedenken, dass die Ausführung des Schalters mit dem nächsten Befehl fortgesetzt wird, wenn im Fallabschnitt (siehe nächster Abschnitt) kein Unterbrechungsbefehl vorhanden ist, bis ein Unterbrechungsbefehl auftritt oder das Ende der Schalteranweisung erreicht ist. Das folgende Beispiel zeigt die Konsequenzen, wenn ein Break-Befehl fehlt: $value = 0.4;

switch($value) :

print „Wert ist 0,4
";

print „Wert ist 0,6
";

print „Wert ist 0,3
";

print „Sie haben keinen Wert ausgewählt!“;

Das Ergebnis sieht so aus:

Das Fehlen eines Unterbrechungsbefehls führte dazu, dass nicht nur der Druckbefehl in dem Abschnitt ausgeführt wurde, in dem die Übereinstimmung gefunden wurde, sondern auch der Druckbefehl im nächsten Abschnitt. Die Befehle in der Switch-Anweisung wurden dann durch einen Switch-Befehl nach dem zweiten Druckbefehl unterbrochen.

Die Wahl zwischen den Befehlen switch und if hat praktisch keinen Einfluss auf die Leistung des Programms. Die Entscheidung, das eine oder andere Design zu verwenden, ist eher eine persönliche Angelegenheit des Programmierers.

Der Befehl break unterbricht sofort die Ausführung der while-, for- oder switch-Anweisung, in der er enthalten ist. Dieser Befehl wurde bereits im vorherigen Abschnitt erwähnt, aber die Unterbrechung der aktuellen Schleife erschöpft nicht die Möglichkeiten des Befehls break. Im Allgemeinen sieht die Break-Syntax wie folgt aus:

Der optionale Parameter n gibt die Anzahl der Ebenen von Kontrollkonstrukten an, die durch den Befehl break beendet werden. Wenn beispielsweise ein Break-Befehl innerhalb von zwei While-Befehlen verschachtelt ist und auf den Break die Zahl 2 folgt, werden beide Schleifen sofort beendet. Der Standardwert für n ist 1; Das Verlassen einer Ebene kann entweder durch explizite Angabe von 1 oder durch Angabe des Befehls break ohne Parameter angegeben werden. Beachten Sie, dass der Befehl if nicht zu den Kontrollkonstrukten gehört, die durch den Befehl break unterbrochen werden können.



 


Lesen:



Optionen „Überall zu Hause“ und „Überall zu Hause in Russland“ MTS - Beschreibung, Kosten, Verbindung

Optionen „Überall zu Hause“ und „Überall zu Hause in Russland“ MTS - Beschreibung, Kosten, Verbindung

Russland nimmt ein riesiges Gebiet unseres Planeten ein. Viele Russen sind mit häufigen Reisen durch ihr Heimatland konfrontiert: Geschäftsreisen, Reisen ...

So stellen Sie ein Windows-Benutzerkennwort wieder her oder setzen es zurück

So stellen Sie ein Windows-Benutzerkennwort wieder her oder setzen es zurück

Wenn Sie plötzlich das Passwort für Ihr Windows-Konto vergessen haben, bleibt Ihnen nichts anderes übrig, als nach einer Möglichkeit zu suchen, es zurückzusetzen oder festzulegen ...

So entfernen Sie Avast vollständig. Programm zum Entfernen von Avast

So entfernen Sie Avast vollständig. Programm zum Entfernen von Avast

Ein spezielles Dienstprogramm zum vollständigen und korrekten Entfernen von Avast Antivirus vom System. Das Programm wurde vom offiziellen Entwicklungsteam erstellt...

Aliexpress-Mobilanwendung

Aliexpress-Mobilanwendung

Heutzutage schreitet der Fortschritt voran und es wird immer beliebter, wenn das Geschäft über eine mobile Anwendung verfügt. Aliexpress ist keine Ausnahme. Navigation...

Feed-Bild RSS