1. Jedes n-te Element finden
In den nachfolgenden Beispielen wird jeweils ein Array definiert, welches die römischen Zahlen zwischen 1 und 10 als Schhlüssel enthält (I, II, III, ..., X) und jeder dieser Zahlen den passenden Dezimalwert zuordnet. Ziel ist es nun, aus diesem Array ein zweites Array abzuleiten, welches jedes dritte Element, beginnend mit "III" enthält. Die Methode dabei soll so gewählt sein, dass sie sich prinzipiell auf jeden beliebigen anderen Abstand abändern lässt (zum Beispiel jedes fünfte Element).
1.1. foreach-Schleife
Als erstes wird die Verwendung einer foreach-Schleife vorgestellt. Diese iteriert hier über alle Schlüssel, welche mit array_keys($arr) ausgelesen wurden. (array_keys($arr) gibt ein Array zurück, welches alle Schlüssel des Arrays $arr als Werte enthält.) Da es Ziel ist, jeden dritten Wert, beginnend beim Schlüssel "III", auszulesen, wird nun der Index jedes Schlüssels betrachtet. Zu diesem muss über den Modulo-Operator (%) der Rest berechnet werden, der bei einer Division durch drei entsteht. Bei den Schlüsseln 0, 1, 2, 3 wären dies entsprechend 0, 1, 2, 0. Jetzt könnte man entweder jeweils prüfen, ob der Rest exakt 2 ist oder vor der Modulo-Operation noch eins addieren, wodurch aus 0, 1, 2, 3 etwa 1, 2, 3, 4 wird mit den Resten 1, 2, 0, 1 (entsprechend würden diese Reste mit 0 verglichen werden). Im Beispiel wird der zweite Weg gewählt, also der Index des Schlüssels vor Modulo um eins erhöht. Ist das Ergebnis von (Index des Schlüssels % 3) nun genau 0, dann handelt es sich um einen Schlüssel aus der Menge „jeder dritte Schlüssel, beginnend bei III”. Dieser wird entsprechend zum Rückgabearray $out hinzugefügt. (Da der Schlüssel bekannt ist, lässt sich der zugehörige Wert aus $arr ableiten.)
<?php $arr = array('I' => 1, 'II' => 2, 'III' => 3, 'IV' => 4, 'V' => 5, 'VI' => 6, 'VII' => 7, 'VIII' => 8, 'IX' => 9, 'X' => 10); $n = 3; $keys = array_keys($arr); // über die Schlüssel soll hier iteriert werden $out = array(); // Rückgabearray foreach ($keys as $indexOfKey=>$key) { // Wenn gilt: Position des Schlüssels + 1 geteilt durch 3 ergibt den Rest 0 // (bei nur $indexOfKey % 3 === 0 würden "I"=>1 (Index 0), "IV"=>4 (Index 3), // "VII"=>7 (Index 6) und "X"=>10 (Index 9) zurückgegeben werden) if (($indexOfKey + 1) % $n === 0) { // ... dann füge den Schlüssel mit dem zugehörigen Wert zum Rückgabearray hinzu $out[$key] = $arr[$key]; } } var_dump($out); ?>
array(3) { ["III"]=> int(3) ["VI"]=> int(6) ["IX"]=> int(9) }
1.2. for-Schleife
Im nächsten Beispiel wird die foreach-Schleife durch eine for-Schleife ausgetauscht. In dieser wird das aktuelle Schlüssel-Wert-Paar der jeweiligen Iteration über each($arr) bestimmt. each($arr) gibt das Schlüssel-Wert-Paar desjenigen Elements als Array zurück, auf das der interne Array-Zeiger gerade gerichtet ist. Vor der for-Schleife wurde dieser über reset($arr) auf den Anfang des Arrays gesetzt. Mit jedem Aufruf von each($arr) wird er eins weiter zum Ende hin bewegt. Das Rückgabearray von each() enthält den Schlüssel des Elements an Index 0 und den Wert an Index 1.
<?php $arr = array('I' => 1, 'II' => 2, 'III' => 3, 'IV' => 4, 'V' => 5, 'VI' => 6, 'VII' => 7, 'VIII' => 8, 'IX' => 9, 'X' => 10); $n = 3; $out = array(); reset($arr); for ($x=1, $c=count($arr); $x<=$c; ++$x) { $pair = each($arr); if ($x % $n === 0) { $out[$pair[0]] = $pair[1]; } } var_dump($out); ?>
array(3) { ["III"]=> int(3) ["VI"]=> int(6) ["IX"]=> int(9) }
1.3. array_filter()
Das nächste Beispiel zeigt die Anwendung von array_filter($arr, $callback). Diese Funktion wendet die Callback-Funktion auf alle Elemente in $arr an und entfernt aus seiner Rückgabe alle Elemente, für die die Callback-Funktion (bool)false zurückgibt. Wie bei der for-Schleife wird eine Zählvariable $x beim Durchlaufen des Arrays hochgezählt. So kann die aktuelle Position bestimmt werden, welche vorgibt, ob das Element im Array verbleiben soll.
<?php $arr = array('I' => 1, 'II' => 2, 'III' => 3, 'IV' => 4, 'V' => 5, 'VI' => 6, 'VII' => 7, 'VIII' => 8, 'IX' => 9, 'X' => 10); $n = 3; $x = 1; // an die Callback-Funktion muss $x als Referenz übergeben werden, damit die Änderungen an // der Variable das Ende jedes Callback-Aufrufs "überleben" $out = array_filter($arr, function($val) use (&$x, $n) { // $x++ hat geringe Gewichtung und wird erst NACH $x % $n ausgeführt, hat also // auf das Ergebnis hier keinen Einfluss und verändert nur den Wert von $x bei der // nächsten Iteration. return ($x++ % $n === 0); }); var_dump($out); ?>
array(3) { ["III"]=> int(3) ["VI"]=> int(6) ["IX"]=> int(9) }
2. Jedes Vielfache eines Wertes finden
Die nächsten Beispiele beschäftigen sich mit der Aufgabenstellung, unter allen Werten in einem Array diejenigen zu finden, die Vielfache einer bestimmten Zahl sind. Wie im vorherigen Abschnitt wird dazu auch hier der Modulo-Operator genutzt. Mit diesem wird jeder einzelne Wert durch die gewünschte Zahl (deren Vielfache gesucht werden) geteilt und der Rest bestimmt. Nur wenn dieser Rest exakt 0 ergibt, lässt sich der Wert glatt durch die Zahl teilen und ist damit eines von deren Vielfachen.
2.1. foreach-Schleife
Die Funktionsweise der foreach-Schleife hier ist ähnlich zu der weiter oben vorgestellten. Diesmal fällt allerdings das Bestimmen der Schlüssel weg und die Berechnung des Rests ist etwas einfacher. Das sonstige Prinzip ist gleich: Über alle Werte iterieren, jeden per Modulo durch $n teilen (die Vielfachen von $n sollen gesucht werden) und falls das ganze den Rest 0 ergibt, wird der Wert zur Rückgabe hinzugefügt.
<?php $arr = array('a' => 3, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3, 'f' => 4, 'g' => 5, 'h' => 6, 'i' => 7); $n = 3; // Vielfach dieser Zahl finden $out = array(); // Rückgabearray foreach ($arr as $key=>$val) { // lässt sich der Wert glatt durch $n teilen, // ist also eines von deren Vielfachen? if ($val % $n === 0) { // Ist ein Vielfaches, zur Rückgabe hinzufügen $out[$key] = $val; } } var_dump($out); ?>
array(3) { ["a"]=> int(3) ["e"]=> int(3) ["h"]=> int(6) }
2.2. while-Schleife mit each()
Die while-Schleife hier arbeitet ähnlich wie die for-Schleife weiter oben. Da keine Zählvariable $x mehr benötigt wird, konnte aber aus for ein while gemacht werden. Es wird wieder each() verwendet, um nacheinander jedes Schlüssel-Wert-Paar auszulesen. Genauso wie im vorherigen Beispiel wird jeder Wert per Modulo durch $n geteilt und der Rest ermittelt, welcher 0 sein muss, damit der Wert ein Vielfaches von $n ist.
<?php $arr = array('a' => 3, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3, 'f' => 4, 'g' => 5, 'h' => 6, 'i' => 7); $n = 3; $out = array(); reset($arr); while ($pair = each($arr)) { if ($pair[1] % $n === 0) { $out[$pair[0]] = $pair[1]; } } var_dump($out); ?>
array(3) { ["a"]=> int(3) ["e"]=> int(3) ["h"]=> int(6) }
2.3. array_filter()
Auch hier kann wieder array_filter() angewendet werden und wie bei der while-Schleife entfällt auch hier die Zählvariable. Diese Methode ist vermutlich die eleganteste, da sie letztlich auf die eigentliche Berechnung reduziert ist und man sich das explizite Zuweisen jedes Schlüssel-Wert-Paares zum Rückgabearray sparen kann.
<?php $arr = array('a' => 3, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3, 'f' => 4, 'g' => 5, 'h' => 6, 'i' => 7); $n = 3; $out = array_filter($arr, function($val) use ($n) { return ($val % $n === 0); }); var_dump($out); ?>
array(3) { ["a"]=> int(3) ["e"]=> int(3) ["h"]=> int(6) }