Die anderen Antworten zeigen den Unterschied zwischen array_walk (direkte Änderung) und array_map (modifizierte Kopie zurückgeben) recht gut. Array_reduce wird jedoch nicht wirklich erwähnt. Dies ist eine aufschlussreiche Methode, um array_map und array_filter zu verstehen.
Die Funktion array_reduce verwendet ein Array, eine Funktion mit zwei Argumenten und einen 'Akkumulator' wie folgt:
array_reduce(array('a', 'b', 'c', 'd'),
'my_function',
$accumulator)
Die Elemente des Arrays werden unter Verwendung der angegebenen Funktion einzeln mit dem Akkumulator kombiniert. Das Ergebnis des obigen Aufrufs ist dasselbe wie folgt:
my_function(
my_function(
my_function(
my_function(
$accumulator,
'a'),
'b'),
'c'),
'd')
Wenn Sie lieber in Schleifen denken möchten, gehen Sie wie folgt vor (ich habe dies tatsächlich als Fallback verwendet, als array_reduce nicht verfügbar war):
function array_reduce($array, $function, $accumulator) {
foreach ($array as $element) {
$accumulator = $function($accumulator, $element);
}
return $accumulator;
}
Diese Schleifenversion macht deutlich, warum ich das dritte Argument als "Akkumulator" bezeichnet habe: Wir können es verwenden, um Ergebnisse durch jede Iteration zu akkumulieren.
Was hat das mit array_map und array_filter zu tun? Es stellt sich heraus, dass beide eine bestimmte Art von array_reduce sind. Wir können sie folgendermaßen umsetzen:
array_map($function, $array) === array_reduce($array, $MAP, array())
array_filter($array, $function) === array_reduce($array, $FILTER, array())
Ignorieren Sie die Tatsache, dass array_map und array_filter ihre Argumente in einer anderen Reihenfolge verwenden. Das ist nur eine weitere Besonderheit von PHP. Der wichtige Punkt ist, dass die rechte Seite bis auf die Funktionen, die ich $ MAP und $ FILTER genannt habe, identisch ist. Wie sehen sie also aus?
$MAP = function($accumulator, $element) {
$accumulator[] = $function($element);
return $accumulator;
};
$FILTER = function($accumulator, $element) {
if ($function($element)) $accumulator[] = $element;
return $accumulator;
};
Wie Sie sehen können, nehmen beide Funktionen den $ -Akkumulator auf und geben ihn erneut zurück. Bei diesen Funktionen gibt es zwei Unterschiede:
- $ MAP wird immer an $ accumulator angehängt, aber $ FILTER tut dies nur, wenn $ function ($ element) TRUE ist.
- $ FILTER hängt das ursprüngliche Element an, aber $ MAP hängt die $ -Funktion ($ element) an.
Beachten Sie, dass dies alles andere als nutzlose Kleinigkeiten sind. Wir können es verwenden, um unsere Algorithmen effizienter zu machen!
Wir können oft Code wie diese beiden Beispiele sehen:
// Transform the valid inputs
array_map('transform', array_filter($inputs, 'valid'))
// Get all numeric IDs
array_filter(array_map('get_id', $inputs), 'is_numeric')
Wenn Sie array_map und array_filter anstelle von Schleifen verwenden, sehen diese Beispiele sehr gut aus. Es kann jedoch sehr ineffizient sein, wenn $ input groß ist, da der erste Aufruf (Map oder Filter) $ input durchläuft und ein Zwischenarray erstellt. Dieses Zwischenarray wird direkt an den zweiten Aufruf übergeben, der das Ganze erneut durchläuft. Dann muss das Zwischenarray mit Müll gesammelt werden.
Wir können dieses Zwischenarray loswerden, indem wir die Tatsache ausnutzen, dass array_map und array_filter beide Beispiele für array_reduce sind. Wenn wir sie kombinieren, müssen wir $ input in jedem Beispiel nur einmal durchlaufen:
// Transform valid inputs
array_reduce($inputs,
function($accumulator, $element) {
if (valid($element)) $accumulator[] = transform($element);
return $accumulator;
},
array())
// Get all numeric IDs
array_reduce($inputs,
function($accumulator, $element) {
$id = get_id($element);
if (is_numeric($id)) $accumulator[] = $id;
return $accumulator;
},
array())
HINWEIS: Meine Implementierungen von array_map und array_filter oben verhalten sich nicht genau wie die von PHP, da meine array_map jeweils nur ein Array verarbeiten kann und mein array_filter nicht "leer" als Standardfunktion für $ verwendet. Außerdem werden keine Schlüssel beibehalten.
Es ist nicht schwer, sie dazu zu bringen, sich wie PHPs zu verhalten, aber ich hatte das Gefühl, dass diese Komplikationen es schwieriger machen würden, die Kernidee zu erkennen.