In PHP ist Array_walk_recursive eine häufig verwendete Funktion, die eine Art von Operation in jedem Element in einem mehrdimensionalen Array ausführt. Während diese Funktion beim Umgang mit kleinen Arrays gut abschneidet, kann sie zu einer Unterperformance werden, wenn das Array sehr groß wird. In diesem Artikel wird untersucht, wie Sie Array_WALK_RECURSIVE optimieren, um große mehrdimensionale Arrays effizient zu verarbeiten.
Die grundlegende Funktion von array_walk_recursive besteht darin, rekursiv durch ein mehrdimensionales Array zu iterieren und eine Rückruffunktion auf jedes Array -Element anzuwenden. Die Signatur dieser Funktion lautet wie folgt:
<span><span><span class="hljs-keyword">bool</span></span><span> </span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span> ( </span><span><span class="hljs-keyword">array</span></span><span> &</span><span><span class="hljs-variable">$array</span></span><span> , </span><span><span class="hljs-keyword">callable</span></span><span> </span><span><span class="hljs-variable">$callback</span></span><span> )
</span></span>
$ array : Ein Array, das an die Funktion übergeben wurde (übergeben von Referenz).
$ Callback : Die Rückruffunktion, die zwei Parameter akzeptiert, ist der erste der Wert des Arrays und der zweite der Schlüssel des Arrays.
Beispielsweise arbeitet der folgende Code rekursiv auf einem zweidimensionalen Array:
<span><span><span class="hljs-variable">$array</span></span><span> = [
</span><span><span class="hljs-string">'a'</span></span><span> => </span><span><span class="hljs-number">1</span></span><span>,
</span><span><span class="hljs-string">'b'</span></span><span> => [
</span><span><span class="hljs-string">'c'</span></span><span> => </span><span><span class="hljs-number">2</span></span><span>,
</span><span><span class="hljs-string">'d'</span></span><span> => </span><span><span class="hljs-number">3</span></span><span>
]
];
</span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>, function(&</span><span><span class="hljs-variable">$item</span></span><span>, </span><span><span class="hljs-variable">$key</span></span><span>) {
</span><span><span class="hljs-variable">$item</span></span><span> *= </span><span><span class="hljs-number">2</span></span><span>; </span><span><span class="hljs-comment">// Multiplizieren Sie jedes Element im Array mit 2</span></span><span>
});
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span></span>
Das Ausgangsergebnis ist:
<span><span><span class="hljs-title function_ invoke__">Array</span></span><span>
(
[a] => </span><span><span class="hljs-number">2</span></span><span>
[b] => </span><span><span class="hljs-title function_ invoke__">Array</span></span><span>
(
[c] => </span><span><span class="hljs-number">4</span></span><span>
[d] => </span><span><span class="hljs-number">6</span></span><span>
)
)
</span></span>
Obwohl Array_walk_recursive eine sehr prägnante und bequeme Funktion ist, verfügt es auch über einige Leistungs Engpässe, insbesondere wenn es sich um große Datenmengen handelt:
Rekursive Anrufaufwand : Array_walk_recursive hängt von der Rekursion ab, um mehrdimensionale Arrays zu durchqueren. Jeder rekursive Aufruf erhöht die Tiefe des Funktionsstapels. Wenn das Array -verschachtelte Schichten tief sind, kann es einen Stapelüberlauf oder die Leistungsverschlechterung verursachen.
Wiederholen Sie die Berechnung : In einigen Fällen arbeitet Array_walk_recursive auf jeder Schicht des Arrays. Wenn der Betrieb komplex ist oder das Array groß ist, wirkt sich dies erheblich auf die Leistung aus.
Um die Leistung von array_walk_recursive zu optimieren, können wir die folgenden Strategien ausprobieren:
Stellen Sie zunächst sicher, dass wir nur auf den Array -Schichten arbeiten, die eine rekursive Verarbeitung benötigen. Bei nicht-multi-dimensionalen Arrays ist es effizienter, Array_Walk oder foreach direkt zu verwenden. Zum Beispiel:
<span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">optimized_walk</span></span><span>(</span><span><span class="hljs-params">&<span class="hljs-variable">$array</span></span></span><span>) {
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$array</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$key</span></span><span> => &</span><span><span class="hljs-variable">$value</span></span><span>) {
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">is_array</span></span><span>(</span><span><span class="hljs-variable">$value</span></span><span>)) {
</span><span><span class="hljs-title function_ invoke__">optimized_walk</span></span><span>(</span><span><span class="hljs-variable">$value</span></span><span>); </span><span><span class="hljs-comment">// Rekursiver Betrieb</span></span><span>
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-variable">$value</span></span><span> *= </span><span><span class="hljs-number">2</span></span><span>; </span><span><span class="hljs-comment">// Verarbeitung einzelner Elemente</span></span><span>
}
}
}
</span><span><span class="hljs-variable">$array</span></span><span> = [
</span><span><span class="hljs-string">'a'</span></span><span> => </span><span><span class="hljs-number">1</span></span><span>,
</span><span><span class="hljs-string">'b'</span></span><span> => [
</span><span><span class="hljs-string">'c'</span></span><span> => </span><span><span class="hljs-number">2</span></span><span>,
</span><span><span class="hljs-string">'d'</span></span><span> => </span><span><span class="hljs-number">3</span></span><span>
]
];
</span><span><span class="hljs-title function_ invoke__">optimized_walk</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span></span>
Auf diese Weise vermeiden wir den rekursiven Overhead von Array_walk_recursive und können die tiefe rekursive Tiefe genauer steuern.
In array_walk_recursive ist der erste Parameter der Rückruffunktion der Wert des Array -Elements. Wenn Sie den Wert des Arrays ändern möchten, müssen Sie den Parameter mit Referenz ( & ) übergeben. Dies erfordert besondere Aufmerksamkeit bei der Optimierung.
Bei der Verwendung von Referenzen kann das Kopieren von Speicherkopierungen reduziert werden, insbesondere im Umgang mit großen Arrays. Zum Beispiel:
<span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>, function (&</span><span><span class="hljs-variable">$value</span></span><span>, </span><span><span class="hljs-variable">$key</span></span><span>) {
</span><span><span class="hljs-variable">$value</span></span><span> *= </span><span><span class="hljs-number">2</span></span><span>;
});
</span></span>
Auf diese Weise vermeidet der & $ Value -Pass eine große Menge an Datenreplikation und verringert den Speicherverbrauch.
Jeder rekursive Aufruf erhöht die Tiefe des Funktionsstapels. Zu große Tiefe führt zu Leistungsproblemen und sogar zu einem Stapelüberlauf. Daher ist die Reduzierung der Anzahl der rekursiven Schichten erheblich hilfreich für die Leistungsverbesserung. Erwägen Sie, eine Warteschlange ( Warteschlange ) oder eine Stapeldatenstruktur zu verwenden, um die Rekursion zu simulieren, wodurch mehrere Funktionsaufrufe und Stapel -Tiefenwachstum vermieden werden können.
Beispiel:
<span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">iterative_walk</span></span><span>(</span><span><span class="hljs-params">&<span class="hljs-variable">$array</span></span></span><span>) {
</span><span><span class="hljs-variable">$stack</span></span><span> = [&</span><span><span class="hljs-variable">$array</span></span><span>]; </span><span><span class="hljs-comment">// Verwenden Sie Stack, um die Rekursion zu simulieren</span></span><span>
</span><span><span class="hljs-keyword">while</span></span><span> (</span><span><span class="hljs-variable">$stack</span></span><span>) {
</span><span><span class="hljs-variable">$current</span></span><span> = </span><span><span class="hljs-title function_ invoke__">array_pop</span></span><span>(</span><span><span class="hljs-variable">$stack</span></span><span>);
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$current</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$key</span></span><span> => &</span><span><span class="hljs-variable">$value</span></span><span>) {
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">is_array</span></span><span>(</span><span><span class="hljs-variable">$value</span></span><span>)) {
</span><span><span class="hljs-variable">$stack</span></span><span>[] = &</span><span><span class="hljs-variable">$value</span></span><span>; </span><span><span class="hljs-comment">// Wenn es ein Array ist,Drücken Sie weiter auf den Stapel</span></span><span>
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-variable">$value</span></span><span> *= </span><span><span class="hljs-number">2</span></span><span>; </span><span><span class="hljs-comment">// Verarbeitungselemente</span></span><span>
}
}
}
}
</span><span><span class="hljs-variable">$array</span></span><span> = [
</span><span><span class="hljs-string">'a'</span></span><span> => </span><span><span class="hljs-number">1</span></span><span>,
</span><span><span class="hljs-string">'b'</span></span><span> => [
</span><span><span class="hljs-string">'c'</span></span><span> => </span><span><span class="hljs-number">2</span></span><span>,
</span><span><span class="hljs-string">'d'</span></span><span> => </span><span><span class="hljs-number">3</span></span><span>
]
];
</span><span><span class="hljs-title function_ invoke__">iterative_walk</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span></span>
In diesem Beispiel verwenden wir eine Stapelstruktur, um die Rekursion zu simulieren und den Overhead rekursiver Anrufe zu vermeiden.
Für gekachelte mehrdimensionale Arrays können wir bei der Kenntnis der Struktur des Arrays anstelle von rekursiven Operationen Array_Map oder Array_Merge verwenden. Diese Funktionen sind normalerweise schneller als array_walk_recursive , da sie intern optimiert werden.
Verwenden Sie beispielsweise Array_MAP , um Prozess -Arrays zu stapeln:
<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-number">1</span></span><span>, </span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>, </span><span><span class="hljs-number">4</span></span><span>];
</span><span><span class="hljs-variable">$result</span></span><span> = </span><span><span class="hljs-title function_ invoke__">array_map</span></span><span>(function(</span><span><span class="hljs-variable">$item</span></span><span>) {
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$item</span></span><span> * </span><span><span class="hljs-number">2</span></span><span>;
}, </span><span><span class="hljs-variable">$array</span></span><span>);
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$result</span></span><span>);
</span></span>
Obwohl diese Methode für eindimensionale Arrays geeignet ist, ist bei der Optimierung mehrdimensionaler Arrays zuerst versucht, das Array in eindimensionales Array umzuwandeln und dann die Leistung erheblich zu verbessern.
Obwohl Array_walk_recursive eine sehr leistungsstarke Funktion ist, ist es nicht immer am besten, um große Arrays zu behandeln. Durch die Vermeidung unnötiger Rekursion, die Verwendung von Referenzen, die Reduzierung der Stapeltiefe und die Verwendung anderer Array -Manipulationsfunktionen können wir die Ausführungseffizienz unseres Codes effektiv verbessern.
Bei der Optimierung der Durchlaufleistung von mehrdimensionalen Arrays liegt der Schwerpunkt darauf, den Aufwand rekursiver Anrufe zu verringern und Array-Elemente mehrmals zu kopieren. Betrachten Sie bei der Begegnung mit großen Arrays eine Rekursion, die durch Iteration oder andere effizientere Lösungen ersetzt wurde.