1. Beidseitiges trim, wenn Schlüssel durchnummeriert sind
In diesem Beispiel werden aus einem Array links- und rechtsseitig alle Elemente entfernt, deren Wert identisch ist mit (bool)false, NULL oder einem leeren String. Linksseitig (und vergleichbar rechtsseitig) heißt, dass besagte Elemente so lange links weggekürzt werden, bis das erste Element entdeckt wird, dass keinen der angegebenen Werte hat und damit im Array verbleiben soll. Die Funktionsweise ist also ähnlich zu trim() bei Strings, welches vom Anfang und Ende des Strings alle Whitespace-Zeichen (Leerzeichen, Zeilenumbrüche, Tabs) entfernt.
Das Vorgehen im Beispiel ist wie folgt:
- Es wird ein Array $arr erzeugt, welches sowohl links (am Anfang) als auch rechts (am Ende) Werte enthält, die entfernt werden sollen.
- Es wird ein Array $removeWhat definiert, in dem gespeichert ist, welche Werte entfernt werden sollen (hier: false, NULL und leere Strings).
- Es wird so lange das erste Element des Arrays mit array_shift() entfernt, bis entweder das Ende erreicht ist, oder der Wert am Anfang des Arrays nicht in $removeWhat enthalten ist.
- Es wird so lange das letzte Element des Arrays mit array_pop() entfernt, bis entweder das Array leer ist oder der letzte Wert im Array nicht in $removeWhat enthalten ist.
- $arr wird ausgegeben.
Die Prüfung, ob der Wert eines Elements in $removeWhat enthalten ist, erfolgt über in_array($wert, $array, true), was wiederum (bool)true zurückgibt, wenn der Wert $wert im Array $array enthalten ist (der dritte Parameter erzwingt eine strikte Prüfung, unterschiedliche Datentypen sind also nie gleich).
<?php $arr = array(null, false, 1, 2, 3, ''); $removeWhat = array(false, null, ''); $count = count($arr); $x = 0; // Werte vom Anfang entfernen: // $x<$count = bis maximal zum Ende // $arr[0] = der erste Wert im Array // in_array($arr[0], $removeWhat, true) = solange, wie der erste Wert in $removeWhat enthalten ist while ($x<$count && in_array($arr[0], $removeWhat, true)) { array_shift($arr); $x++; } $count = $count - $x; // count korrigieren, da Elemente entfernt wurden $x = $count - 1; // Werte vom Ende entfernen // $x>=0 = solange das Array nicht leer ist // $arr[$x] = aktuell letzter Wert while ($x>=0 && in_array($arr[$x], $removeWhat, true)) { array_pop($arr); $x--; } print_r($arr); ?>
Array ( [0] => 1 [1] => 2 [2] => 3 )
2. Beidseitiges Array-trim, elegant
Nachfolgend wird das vorherige Beispiel etwas weitergeführt. Die Zählvariable wurde hier entfernt, indem stattdessen auf current() zurückgegriffen wird. current($arr) gibt den Wert des Elements zurück, auf den der interne Array-Zeiger gerade gerichtet ist. Über reset($arr) wird dieser am Anfang auf das erste Element des Arrays gesetzt. So ergibt in_array(trim(current($copy)), $removeWhat, true) immer dann (bool)true, wenn das erste Element im Array in $removeWhat enthalten. In diesem Beispiel wird zusätzlich trim() auf jeden Wert angewendet, bevor dieser mit $removeWhat verglichen wird. So werden auch Werte entfernt, die Whitespace-Strings sind (also zum Beispiel nur aus Leerzeichen oder Zeilenumbrüchen bestehen). Um sicher zu stellen, dass das Array bei jeder Iteration noch mindestens einen Wert enthält (und andernfalls abzubrechen), wird diesmal empty() auf das Array angewendet. empty($arr) gibt dann true zurück, wenn das Array $arr leer ist.
Einschränkung: Da trim() einen String zurückgibt, kann diese Konstruktion hier nicht ohne weiteres verwendet werden, um Integer oder Floats vom Anfang/Ende des Arrays zu entfernen. Um dies zu erreichne müsste trim() wieder entfernt werden, oder es müssten zusätzliche if-else-Bedigungen hinzugefügt werden. Die Prüfung von in_array() auf nicht-strikt (dritter Parameter false) zu stellen ist nicht empfehlenswert, sonst gibt es schnell Probleme beim Vergleich zwischen Integern und Strings.
<?php $arr = array(null, false, 1, 2, 3, ''); $removeWhat = array(false, null, ''); $copy = $arr; // Array hier kopieren, damit $arr in seiner ursprünglichen Form erhalten bleibt reset($copy); // wäre _hier_ nicht zwangsweise notwendig // So lange Werte vom Anfang des Arrays entfernen, bis dieses leer ist oder der erste // Wert nicht in $removeWhat enthalten ist // empty($copy) = true wenn $copy leer ist // trim(current($copy)) = gibt die getrimmte Version des ersten Wertes im Array zurück (keine Leerzeichen am Anfang/Ende) while (!empty($copy) && in_array(trim(current($copy)), $removeWhat, true)) { array_shift($copy); } end($copy); // Array-Zeiger auf das Ende des Arrays setzen // So lange Werte vom Ende entfernen, bis $copy leer ist oder der letzte Wert // nicht in $removeWhat enthalten ist while (!empty($copy) && in_array(trim(current($copy)), $removeWhat, true)) { array_pop($copy); } print_r($copy); ?>
Array ( [0] => 1 [1] => 2 [2] => 3 )
3. Linksseitiges Array-trim mit array_shift() und array_unshift()
Nachfolgend wird eine kleine Funktion definiert, die nur auf der linken Seite einen Array-trim durchführt. Die Funktion erwartet ein zu trimmendes Array und optional die zu entfernenden Werte. Das Vorgehen der Funktion ist einfach:
- Es wird so lange eine while-Schleife wiederholt, bis das Array leer ist.
- Bei jedem Schleifendurchlauf wird der erste Wert vom Array entfernt und in $val gespeichert.
- Falls $val nicht zu den zu entfernenden Werten gehört, wird der Wert wieder am Anfang hinzugefügt und die Schleife mit break beendet.
Es wird also so lange das erste Element entfernt bis eines im Array verbleiben soll. Das wird dann wieder am Anfang hinzugefügt und die Schleife wird abgebrochen.
<?php function arrayTrimLeft($arr, $removeWhat=null) { $removeWhat = ($removeWhat===null ? array(false, null, '') : $removeWhat); while (!empty($arr)) { $val = array_shift($arr); if (!in_array($val, $removeWhat, true)) { array_unshift($arr, $val); break; } } return $arr; } $arr1 = array(null, false, 1, 2, 3, ''); $arr2 = array(null, null, null); $arr3 = array(1, 2, 3); $arr4 = array(); print_r(arrayTrimLeft($arr1)); print_r(arrayTrimLeft($arr2)); print_r(arrayTrimLeft($arr3)); print_r(arrayTrimLeft($arr4)); ?>
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => ) Array ( ) Array ( [0] => 1 [1] => 2 [2] => 3 ) Array ( )
4. Linksseitiges Array-trim, alternative Version
Die nächste Funktion arbeitet ähnlich zur vorherigen. Wesentlicher Unterschied ist hier, dass zunächst die Schlüssel des Arrays ausgelesen werden und dann mit diesen gearbeitet wird. Auch hier erledigt eine while-Schleife die wesentliche Arbeit, statt vom Anfang des Arrays wird allerdings vom Anfang des Schlüssel-Arrays immer der erste Wert entfernt. (Das Schlüssel Array, welches alle Schlüssel des Arrays $arr enthält, wird mit array_keys($arr) gebildet.) Nachdem der erste Schlüssel vom Schlüssel-Array entfernt wurde, kann mit diesem auch das erste Element im eigentlichen Array bestimmt werden. Dieses wird dann mit den zu löschenden Werten verglichen. Muss das Element entfernt werden, dann wird einmalig unset() auf seinen Schlüssel angewendet. Andernfalls (Element soll nicht gelöscht werden) wird die Schleife sofort abgebrochen.
<?php function arrayTrimLeft($arr, $removeWhat=null) { $removeWhat = ($removeWhat===null ? array(false, null, '') : $removeWhat); $keys = array_keys($arr); while (!empty($keys)) { $key = array_shift($keys); $val = $arr[$key]; if (in_array($val, $removeWhat, true)) { unset($arr[$key]); } else { break; } } return $arr; } $arr = array(null, false, 1, 2, 3, ''); print_r(arrayTrimLeft($arr)); ?>
Array ( [2] => 1 [3] => 2 [4] => 3 [5] => )
Der wesentliche Vorteil dieser Art der Implementierung ergibt sich aus der Abstraktion. Da mit den Schlüsseln statt mit dem eigentlichen Array gearbeitet wird, kann die Funktion fast identisch auch für ein rechtsseitiges Array-trim verwendet werden. Dafür müssen nur die Schlüssel einmalig per array_reverse() umgedreht werden. Im nachfolgenden Abschnitt wird dies genutzt.
5. Beidseitiges Array-trim
Die vorherige Funktion wird nun für beidseitiges Array-trim erweitert. Dazu muss nur ein weiterer Parameter $keys ergänzt und statt array_keys($arr) in der Funktion verwendet werden. Mit dem bereits beschriebenen Umdrehen der Schlüssel ist die Funktion so nun auf beide „Richtungen” anwendbar. Ergänzt wurde hier zudem, dass noch ein trim() bei jedem Wert durchgeführt wird, sodass zum Beispiel auch Strings entfernt werden, die nur Leerzeichen enthalten.
<?php function arrayTrimByKeys($arr, $keys, $removeWhat=null) { $removeWhat = ($removeWhat===null ? array(false, null, '') : $removeWhat); // kein while ($key = array_shift($keys)), da // auch (int)0 (string)0 und (string)"" gueltige Schluessel sind, // welche wie (bool)false behandelt werden while (!empty($keys)) { $key = array_shift($keys); $val = $arr[$key]; $val = (is_string($val) ? trim($val) : $val); if (in_array($val, $removeWhat, true)) { unset($arr[$key]); } else { break; } } return $arr; } // linksseitiges Array-trim function arrayTrimLeft($arr, $removeWhat=null) { // uebergebene Schlüssel sind normal "von links nach rechts" geordnet return arrayTrimByKeys($arr, array_keys($arr), $removeWhat); } // rechtsseitiges Array-trim function arrayTrimRight($arr, $removeWhat=null) { // Die Schlüssel sind hier mit array_reverse() umgekehrt ("von rechts nach links"), // sodass rechts an mit dem Array-trim begonnen wird und nach links hin entfernt wird return arrayTrimByKeys($arr, array_reverse(array_keys($arr)), $removeWhat); } // beidseitiges Array-trim, führt erst linksseitigen Array-trim durch und dann mit dem Ergebnis // einen rechtsseitigen Array-trim function arrayTrim($arr, $removeWhat=null) { return arrayTrimRight(arrayTrimLeft($arr, $removeWhat), $removeWhat); } $arr = array(null, false, 1, 2, 3, ''); print_r(arrayTrimLeft($arr)); print_r(arrayTrimRight($arr)); print_r(arrayTrim($arr)); ?>
Array ( [2] => 1 [3] => 2 [4] => 3 [5] => ) Array ( [0] => [1] => [2] => 1 [3] => 2 [4] => 3 ) Array ( [2] => 1 [3] => 2 [4] => 3 )
Kommentare (1)
Von neu nach altWir bitten um ihr Verständnis.