Quelle est exactement la différence entre array_map
, array_walk
et array_filter
. Ce que j'ai pu voir dans la documentation, c'est que vous pouvez passer une fonction de rappel pour effectuer une action sur le tableau fourni. Mais je ne semble pas trouver de différence particulière entre eux.
Réalisent-ils la même chose?
Peuvent-ils être utilisés de manière interchangeable?
J'apprécierais votre aide avec un exemple illustratif s'ils sont différents du tout.
Réponses:
array_map
ne peut pas modifier les valeurs à l'intérieur des tableaux d'entrée pendant quearray_walk
can; en particulier,array_map
ne change jamais ses arguments.array_map
ne peut pas fonctionner avec les clés du tableau,array_walk
peut.array_map
renvoie un nouveau tableau,array_walk
ne renvoie quetrue
. Par conséquent, si vous ne souhaitez pas créer un tableau suite à la traversée d'un tableau, vous devez utiliserarray_walk
.array_map
peut également recevoir un nombre arbitraire de tableaux et il peut les parcourir en parallèle, alors qu'ilarray_walk
ne fonctionne que sur un seul.array_walk
peut recevoir un paramètre arbitraire supplémentaire pour passer au rappel. Cela est pratiquement hors de propos depuis PHP 5.3 (lorsque des fonctions anonymes ont été introduites).array_map
a la même longueur que celui du plus grand tableau d'entrée;array_walk
ne renvoie pas de tableau mais en même temps il ne peut pas modifier le nombre d'éléments du tableau d'origine;array_filter
sélectionne uniquement un sous-ensemble des éléments du tableau en fonction d'une fonction de filtrage. Il conserve les clés.Exemple:
Résultat:
la source
array_map(callback($key, $value), array_keys($array), $array)
L'idée de mapper une fonction à un tableau de données vient de la programmation fonctionnelle. Vous ne devriez pas penser à
array_map
uneforeach
boucle qui appelle une fonction sur chaque élément du tableau (même si c'est comme ça qu'elle est implémentée). Cela devrait être considéré comme l'application indépendante de la fonction à chaque élément du tableau.En théorie, des choses telles que le mappage de fonctions peuvent être effectuées en parallèle, car la fonction appliquée aux données ne doit affecter que les données et NON l'état global. En effet, an
array_map
pourrait choisir n'importe quel ordre dans lequel appliquer la fonction aux éléments de (même si en PHP ce n'est pas le cas).array_walk
d'autre part, c'est l'approche exactement opposée à la gestion des tableaux de données. Au lieu de gérer chaque élément séparément, il utilise un état (&$userdata
) et peut modifier l'élément en place (un peu comme une boucle foreach). Étant donné que chaque fois qu'un élément lui est$funcname
appliqué, il peut changer l'état global du programme et nécessite donc une seule manière correcte de traiter les éléments.De retour en PHP,
array_map
etarray_walk
sont presque identiques saufarray_walk
vous donne plus de contrôle sur l'itération des données et est normalement utilisé pour "changer" les données en place par rapport au retour d'un nouveau tableau "modifié".array_filter
est vraiment une application dearray_walk
(ouarray_reduce
) et il est plus ou moins juste fourni pour plus de commodité.la source
array_filter()
peut être mis en œuvre en utilisantarray_walk()
?De la documentation,
array_walk prend un tableau et une fonction
F
et le modifie en remplaçant chaque élément x parF(x)
.array_map fait exactement la même chose sauf qu'au lieu de modifier sur place, il retournera un nouveau tableau avec les éléments transformés.
array_filter avec fonction
F
, au lieu de transformer les éléments, supprimera tous les éléments pour lesquels ceF(x)
n'est pas vraila source
array_walk
renvoyé un tableau similairearray_map
et j'ai pensé que le problème était dans ma fonction. Je n'ai pas réalisé jusqu'à ce que je vois cela que le type de retour est booléen.Les autres réponses démontrent assez bien la différence entre array_walk (modification sur place) et array_map (retour de la copie modifiée). Cependant, ils ne mentionnent pas vraiment array_reduce, ce qui est un moyen éclairant de comprendre array_map et array_filter.
La fonction array_reduce prend un tableau, une fonction à deux arguments et un 'accumulateur', comme ceci:
Les éléments du tableau sont combinés avec l'accumulateur un par un, en utilisant la fonction donnée. Le résultat de l'appel ci-dessus est le même que celui-ci:
Si vous préférez penser en termes de boucles, c'est comme faire ce qui suit (je l'ai en fait utilisé comme solution de rechange lorsque array_reduce n'était pas disponible):
Cette version en boucle explique pourquoi j'ai appelé le troisième argument un «accumulateur»: nous pouvons l'utiliser pour accumuler des résultats à chaque itération.
Alors qu'est-ce que cela a à voir avec array_map et array_filter? Il s'avère qu'ils sont tous deux un type particulier de array_reduce. Nous pouvons les implémenter comme ceci:
Ignorez le fait que array_map et array_filter prennent leurs arguments dans un ordre différent; c'est juste une autre bizarrerie de PHP. Le point important est que le côté droit est identique à l'exception des fonctions que j'ai appelées $ MAP et $ FILTER. Alors, à quoi ressemblent-ils?
Comme vous pouvez le voir, les deux fonctions récupèrent l'accumulateur $ et le renvoient à nouveau. Il existe deux différences dans ces fonctions:
Notez que cela est loin d'être trivial inutile; nous pouvons l'utiliser pour rendre nos algorithmes plus efficaces!
Nous pouvons souvent voir du code comme ces deux exemples:
L'utilisation de array_map et array_filter au lieu de boucles rend ces exemples assez agréables. Cependant, il peut être très inefficace si $ inputs est grand, car le premier appel (carte ou filtre) traversera $ inputs et construira un tableau intermédiaire. Ce tableau intermédiaire est transmis directement dans le deuxième appel, qui traversera à nouveau le tout, puis le tableau intermédiaire devra être récupéré.
Nous pouvons nous débarrasser de ce tableau intermédiaire en exploitant le fait que array_map et array_filter sont tous deux des exemples de array_reduce. En les combinant, nous n'avons à parcourir $ inputs qu'une seule fois dans chaque exemple:
REMARQUE: Mes implémentations de array_map et array_filter ci-dessus ne se comporteront pas exactement comme PHP, car mon array_map ne peut gérer qu'un seul tableau à la fois et mon array_filter n'utilisera pas "empty" comme fonction $ par défaut. De plus, aucun ne conservera les clés.
Il n'est pas difficile de les faire se comporter comme PHP, mais je sentais que ces complications rendraient l'idée de base plus difficile à repérer.
la source
La révision suivante cherche à délimiter plus clairement array_filer (), array_map () et array_walk () de PHP, qui proviennent tous de la programmation fonctionnelle:
array_filter () filtre les données, produisant ainsi un nouveau tableau contenant uniquement les éléments souhaités de l'ancien tableau, comme suit:
code en direct ici
Toutes les valeurs numériques sont filtrées hors du tableau $, laissant $ filtré avec uniquement les types de fruits.
array_map () crée également un nouveau tableau mais contrairement à array_filter () le tableau résultant contient chaque élément de l'entrée $ filtré mais avec des valeurs modifiées, en raison de l'application d'un rappel à chaque élément, comme suit:
code en direct ici
Dans ce cas, le code applique un rappel à l'aide de strtoupper () intégré, mais une fonction définie par l'utilisateur est également une autre option viable. Le rappel s'applique à chaque élément de $ filtré et engendre ainsi $ nu dont les éléments contiennent des valeurs majuscules.
Dans l'extrait suivant, le tableau walk () traverse $ nu et modifie chaque élément par rapport à l'opérateur de référence '&'. Les modifications se produisent sans créer de tableau supplémentaire. La valeur de chaque élément se transforme en une chaîne plus informative spécifiant sa clé, sa catégorie et sa valeur.
Voir la démo
Remarque: la fonction de rappel par rapport à array_walk () prend deux paramètres qui acquerront automatiquement la valeur d'un élément et sa clé et dans cet ordre, également lorsqu'elle est invoquée par array_walk (). (Voir plus ici ).
la source
$lambda
et ne$callback
sont que des extensions eta des fonctions existantes, et sont donc complètement redondantes. Vous pouvez obtenir le même résultat en passant (le nom de) la fonction sous-jacente:$filtered = array_filter($array, 'ctype_alpha');
et$nu = array_map('strtoupper', $filtered);