Dans PHP, Array_Walk_Recursive est une fonction couramment utilisée qui effectue une sorte de fonctionnement sur chaque élément dans un tableau multidimensionnel. Bien que cette fonction fonctionne bien lorsqu'il s'agit de tableaux à petite échelle, il peut devenir sous-performant lorsque le tableau devient très grand. Cet article explorera comment optimiser Array_walk_recursive pour gérer efficacement les grands tableaux multidimensionnels.
La fonction de base de Array_Walk_Recursive est d'itérer récursivement via un tableau multidimensionnel et d'appliquer une fonction de rappel à chaque élément de tableau. La signature de cette fonction est la suivante:
<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 : un tableau transmis à la fonction (passé par référence).
$ rappel : la fonction de rappel, qui accepte deux paramètres, la première est la valeur du tableau et la seconde est la clé du tableau.
Par exemple, le code suivant fonctionne récursivement sur un tableau bidimensionnel:
<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">// Multiplier chaque élément du tableau par 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>
Le résultat de la sortie est:
<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>
Bien que Array_Walk_Recursive soit une fonction très concise et pratique, il a également des goulots d'étranglement de performances, en particulier lorsqu'ils traitent de grandes quantités de données:
Offres récursives d'appel : array_walk_recursive dépend de la récursivité pour traverser les tableaux multidimensionnels. Chaque appel récursif augmente la profondeur de la pile de fonction. Lorsque les couches imbriquées du tableau sont profondes, elle peut provoquer un débordement de pile ou une dégradation des performances.
Répéter le calcul : dans certains cas, Array_Walk_Recursive fonctionne sur chaque couche du tableau. Si l'opération est complexe ou que le tableau est important, cela affectera considérablement les performances.
Afin d'optimiser les performances de Array_Walk_Recursive , nous pouvons essayer les stratégies suivantes:
Tout d'abord, assurez-vous que nous ne fonctionnons que sur les couches de tableau qui nécessitent un traitement récursif. Pour les tableaux non dimensionnels, il est plus efficace d'utiliser Array_walk ou directement directement. Par exemple:
<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">// Opération récursive</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">// Traitement des éléments individuels</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>
De cette façon, nous évitons les frais généraux récursifs de Array_Walk_Recursive et pouvons contrôler la profondeur de récursif plus précisément.
Dans array_walk_recursive , le premier paramètre de la fonction de rappel est la valeur de l'élément de tableau. Si vous souhaitez modifier la valeur du tableau, vous devez passer le paramètre par référence ( & ). Cela nécessite une attention particulière lors de l'optimisation.
Lorsque vous utilisez des références, la copie des frais généraux peut être réduite, en particulier lorsqu'il s'agit de grands tableaux. Par exemple:
<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>
De cette façon, la valeur de valeur & $ évite de grandes quantités de réplication de données et réduit l'utilisation de la mémoire.
Chaque appel récursif augmentera la profondeur de la pile de fonction. Une profondeur trop grande entraînera des problèmes de performances et même un débordement de pile. Par conséquent, la réduction du nombre de couches récursives est considérablement utile pour l'amélioration des performances. Envisagez d'utiliser une file d'attente ( file d'attente ) ou de la structure de données de pile pour simuler la récursivité, ce qui peut éviter plusieurs appels de fonction et la croissance de la profondeur de pile.
Exemple:
<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">// Utilisez la pile pour simuler la récursivité</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">// Si c'est un tableau,Continuez à appuyer sur la pile</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">// Éléments de traitement</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>
Dans cet exemple, nous utilisons une structure de pile pour simuler la récursivité, en évitant les frais généraux des appels récursifs.
Pour les tableaux multidimensionnels carrelés, si nous connaissons la structure du tableau, nous pouvons utiliser array_map ou array_merge au lieu d'opérations récursives. Ces fonctions sont généralement plus rapides que Array_Walk_Recursive car elles sont optimisées en interne.
Par exemple, utilisez Array_Map pour organiser les tableaux de processus:
<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>
Bien que cette méthode convient aux tableaux unidimensionnels, lors de l'optimisation des tableaux multidimensionnels, essayant d'abord de convertir le tableau en réseau unidimensionnel, puis de traiter, il peut améliorer considérablement les performances.
Bien que Array_Walk_Recursive soit une fonction très puissante, il n'est pas toujours préférable de gérer de grands tableaux. En évitant la récursivité inutile, en utilisant des références, en réduisant la profondeur de la pile et en utilisant d'autres fonctions de manipulation du tableau, nous pouvons améliorer efficacement l'efficacité d'exécution de notre code.
Lors de l'optimisation des performances de traversée des tableaux multidimensionnels, l'objectif est de réduire les frais généraux des appels récursifs et d'éviter de copier les éléments de tableau plusieurs fois. Lorsque vous rencontrez de grands tableaux, considérez la récursivité remplacée par l'itération ou d'autres solutions plus efficaces.