Abschnitt 5 · Lektion 4
Arrays umformen
Bis jetzt hast du jede Umformung selbst geschleift: neue Variable anlegen, foreach darüber,
Ergebnis anhängen. Das ist völlig richtig und wird immer funktionieren. Für die drei häufigsten
Fälle gibt es aber je eine fertige Funktion, und der Code wird damit kürzer und vor allem
eindeutiger, weil schon der Name sagt, was passiert.
Jeden Wert durch dieselbe Mühle
<?php
$cent = ["Brot" => 250, "Milch" => 120, "Kaffee" => 490];
// Erst das Ding, das gemacht werden soll, dann die Liste:
$euro = array_map(fn($betrag) => $betrag / 100, $cent);
var_dump($euro);
echo "\nZum Vergleich, von Hand geschrieben:\n";
$selbst = [];
foreach ($cent as $ware => $betrag) {
$selbst[$ware] = $betrag / 100;
}
var_dump($selbst); array_map() nimmt eine Liste und gibt eine neue Liste zurück, die genauso lang ist. Jeder Wert
ist vorher durch deine Funktion gelaufen. Die ursprüngliche Liste bleibt dabei unangetastet, und das
ist ein Unterschied zu den Sortierfunktionen in der nächsten Lektion.
Der zweite Teil des Beispiels zeigt dieselbe Arbeit von Hand. Vier Zeilen statt einer, und die Fehler stecken alle in den vier: die neue Variable vergessen, den Schlüssel verlieren, aus Versehen in die alte Liste schreiben.
Das fn($betrag) => $betrag / 100 ist eine anonyme Funktion, eine Funktion ohne Namen. Links
steht, was hineingeht, rechts, was herauskommt. Mehr musst du hier nicht darüber wissen,
ausführlich kommt das in Lektion 6.6.
Eine Kleinigkeit, die später wichtig wird: Mit einer einzigen Liste behält array_map die
Schlüssel. Aus Brot wird wieder Brot. Gibst du zwei Listen mit, nummeriert es das Ergebnis neu
durch, weil es dann ja nicht wissen kann, wessen Schlüssel gelten sollen.
Nur behalten, was passt
<?php
$zahlen = [10, 20, 30, 40, 50];
// Hier andersherum: erst die Liste, dann die Bedingung.
$gross = array_filter($zahlen, fn($wert) => $wert > 25);
echo "Gefiltert:\n";
var_dump($gross);
echo "\nDer erste Eintrag steht auf Platz 0?\n";
var_dump($gross[0] ?? "gibt es nicht");
echo "\nMit array_values neu nummeriert:\n";
var_dump(array_values($gross)); array_filter() geht die Liste durch und behält jeden Eintrag, für den deine Bedingung true
ergibt. Alles andere fällt raus.
Und jetzt die Sache, die einen beim ersten Mal wirklich erwischt: Die Schlüssel bleiben, wie sie
waren. Fällt der Eintrag auf Platz 0 heraus, fängt das Ergebnis bei Platz 2 an. Kein Fehler, keine
Warnung, es ist einfach so. Wer danach mit $gefiltert[0] zugreift, bekommt genau die Warnung aus
Lektion 5.1 und null obendrauf.
Bei Textschlüsseln ist das genau richtig, dort will man den Namen ja behalten. Bei nummerierten
Listen ist es meistens im Weg, und dann hilft array_values(): Es wirft die Schlüssel weg und
nummeriert von null an neu durch.
Faustregel: Nach einem array_filter auf einer nummerierten Liste kommt array_values.
Zusammenzählen
<?php
$preise = ["Hemd" => 3900, "Socken" => 490, "Hose" => 4200];
$teuer = array_filter($preise, fn($cent) => $cent >= 3000);
$rabatt = array_map(fn($cent) => $cent * 0.9, $teuer);
foreach ($rabatt as $ware => $cent) {
echo $ware, ": ", number_format($cent / 100, 2, ",", "."), "\n";
}
echo "Summe: ", number_format(array_sum($rabatt) / 100, 2, ",", "."), "\n";
echo "Artikel: ", count($rabatt), "\n"; array_sum() addiert alle Werte einer Liste. Das ist die dritte im Bunde und die langweiligste,
aber sie steht selten allein.
Das Beispiel zeigt die übliche Reihenfolge: erst sieben, dann rechnen, dann summieren. Jede Zeile
macht genau eine Sache, und du kannst nach jeder ein var_dump einschieben, um zu sehen, wo es
schiefgeht. Genau so würde ich das auch nach zwanzig Jahren noch bauen.
Beachte, dass hier weiter in Cent gerechnet wird und erst beim Ausgeben durch 100 geteilt wird, so
wie es Lektion 2.3 empfiehlt. Die Formatierung mit number_format kennst du aus Lektion 3.4.
Die verdrehte Reihenfolge
<?php
$zahlen = [1, 2, 3];
// array_map: erst die Funktion, dann die Liste.
var_dump(array_map(fn($z) => $z * 10, $zahlen));
// array_filter: erst die Liste, dann die Funktion.
var_dump(array_filter($zahlen, fn($z) => $z > 1));
// Und ohne Funktion siebt array_filter alles Falsche aus,
// nach der Liste aus Lektion 2.5:
var_dump(array_filter([0, 1, "", "a", null, "0", []])); Zum Schluss die Kleinigkeit, die einen jedes Mal ärgert: array_map will erst die Funktion,
array_filter will erst die Liste. Das ist historisch gewachsen und lässt sich nicht mehr
reparieren, ohne millionenfach vorhandenen Code zu brechen.
Merk dir das nicht. Schlag es nach, wenn du es brauchst, oder lass es dir vom Editor vorschlagen. Wer sich daran festbeißt, verliert Zeit an etwas, das nichts erklärt.
Was du dagegen mitnehmen kannst: array_filter ohne Funktion siebt alles aus, was PHP für
falsch hält. Das ist genau die Liste aus Lektion 2.5, und deshalb überlebt der Text "0" diese
Behandlung nicht. Praktisch zum Aufräumen einer Liste mit Lücken, gefährlich, wenn eine echte Null
darin ein gültiger Wert ist.
Zum Mitnehmen
Aus einer Liste eine andere machen, ohne selbst zu schleifen. Drei Funktionen reichen dafür in den allermeisten Fällen, und sie ersparen dir eine Menge Zeilen, in denen man sich verzählen kann.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 4 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.