¿Cuál es exactamente la diferencia entre array_map
, array_walk
y array_filter
. Lo que pude ver en la documentación es que puede pasar una función de devolución de llamada para realizar una acción en la matriz suministrada. Pero no parece encontrar ninguna diferencia particular entre ellos.
¿Realizan lo mismo?
¿Se pueden usar indistintamente?
Agradecería su ayuda con ejemplos ilustrativos si son diferentes en absoluto.
Respuestas:
array_map
no puede cambiar los valores dentro de la (s) matriz (s) de entrada mientrasarray_walk
puede; en particular,array_map
nunca cambia sus argumentos.array_map
no puede funcionar con las teclas de matriz,array_walk
can.array_map
devuelve una nueva matriz,array_walk
solo devuelvetrue
. Por lo tanto, si no desea crear una matriz como resultado de atravesar una matriz, debe usarlaarray_walk
.array_map
también puede recibir un número arbitrario de matrices y puede iterar sobre ellas en paralelo, mientrasarray_walk
opera solo en una.array_walk
puede recibir un parámetro arbitrario adicional para pasar a la devolución de llamada. Esto es irrelevante desde PHP 5.3 (cuando se introdujeron funciones anónimas ).array_map
tiene la misma longitud que la matriz de entrada más grande;array_walk
no devuelve una matriz, pero al mismo tiempo no puede alterar el número de elementos de la matriz original;array_filter
selecciona solo un subconjunto de los elementos de la matriz de acuerdo con una función de filtrado. Conserva las llaves.Ejemplo:
Resultado:
fuente
array_map(callback($key, $value), array_keys($array), $array)
La idea de asignar una función a una matriz de datos proviene de la programación funcional. No debe pensar en
array_map
unforeach
bucle que llama a una función en cada elemento de la matriz (aunque así es como se implementa). Se debe considerar que aplica la función a cada elemento de la matriz de forma independiente.En teoría, cosas como el mapeo de funciones se pueden hacer en paralelo ya que la función que se aplica a los datos SOLO debería afectar los datos y NO el estado global. Esto se debe a que
array_map
podría elegir cualquier orden en el que aplicar la función a los elementos (aunque en PHP no lo hace).array_walk
por otro lado, es exactamente el enfoque opuesto para manejar matrices de datos. En lugar de manejar cada elemento por separado, utiliza un estado (&$userdata
) y puede editar el elemento en su lugar (como un bucle foreach). Como cada vez que se$funcname
aplica un elemento , puede cambiar el estado global del programa y, por lo tanto, requiere una única forma correcta de procesar los elementos.De vuelta en tierra PHP,
array_map
yarray_walk
son casi idénticos, excepto quearray_walk
le da más control sobre la iteración de datos y normalmente se usa para "cambiar" los datos en el lugar frente a devolver una nueva matriz "cambiada".array_filter
es realmente una aplicación dearray_walk
(oarray_reduce
) y más o menos solo se proporciona por conveniencia.fuente
array_filter()
se puede implementar usandoarray_walk()
?De la documentación,
array_walk toma una matriz y una función
F
y la modifica reemplazando cada elemento x conF(x)
.array_map hace exactamente lo mismo, excepto que en lugar de modificar in situ devolverá una nueva matriz con los elementos transformados.
array_filter con función
F
, en lugar de transformar los elementos, eliminará cualquier elemento para el queF(x)
no sea ciertofuente
array_walk
devolvió una matriz comoarray_map
y pensé que el problema estaba en mi función. No me di cuenta hasta que vi esto que el tipo de retorno es booleano.Las otras respuestas demuestran la diferencia entre array_walk (modificación en el lugar) y array_map (devolución de copia modificada) bastante bien. Sin embargo, en realidad no mencionan array_reduce, que es una forma ilustrativa de comprender array_map y array_filter.
La función array_reduce toma una matriz, una función de dos argumentos y un 'acumulador', así:
Los elementos de la matriz se combinan con el acumulador de uno en uno, utilizando la función dada. El resultado de la llamada anterior es el mismo que hacer esto:
Si prefiere pensar en términos de bucles, es como hacer lo siguiente (en realidad, he usado esto como una alternativa cuando array_reduce no estaba disponible):
Esta versión en bucle deja en claro por qué he llamado al tercer argumento "acumulador": podemos usarlo para acumular resultados a través de cada iteración.
Entonces, ¿qué tiene esto que ver con array_map y array_filter? Resulta que ambos son un tipo particular de array_reduce. Podemos implementarlos así:
Ignore el hecho de que array_map y array_filter toman sus argumentos en un orden diferente; Esa es solo otra peculiaridad de PHP. El punto importante es que el lado derecho es idéntico, excepto por las funciones que he llamado $ MAP y $ FILTER. Entonces, ¿cómo se ven?
Como puede ver, ambas funciones toman el acumulador $ y lo devuelven nuevamente. Hay dos diferencias en estas funciones:
Tenga en cuenta que esto está lejos de ser una trivia inútil; ¡podemos usarlo para hacer que nuestros algoritmos sean más eficientes!
A menudo podemos ver códigos como estos dos ejemplos:
El uso de array_map y array_filter en lugar de bucles hace que estos ejemplos se vean bastante bien. Sin embargo, puede ser muy ineficiente si $ input es grande, ya que la primera llamada (mapa o filtro) atravesará $ input y creará una matriz intermedia. Esta matriz intermedia se pasa directamente a la segunda llamada, que atravesará todo nuevamente, luego la matriz intermedia tendrá que ser recolectada de basura.
Podemos deshacernos de esta matriz intermedia explotando el hecho de que array_map y array_filter son ejemplos de array_reduce. Al combinarlos, solo tenemos que atravesar $ input una vez en cada ejemplo:
NOTA: Mis implementaciones de array_map y array_filter anteriores no se comportarán exactamente como PHP, ya que mi array_map solo puede manejar una matriz a la vez y mi array_filter no usará "vacío" como su función $ predeterminada. Además, ninguno conservará las claves.
No es difícil hacer que se comporten como PHP, pero sentí que estas complicaciones harían que la idea central fuera más difícil de detectar.
fuente
La siguiente revisión busca delinear más claramente los array_filer (), array_map () y array_walk () de PHP, todos los cuales se originan en la programación funcional:
array_filter () filtra datos, produciendo como resultado una nueva matriz que contiene solo los elementos deseados de la matriz anterior, de la siguiente manera:
código en vivo aquí
Todos los valores numéricos se filtran de $ array, dejando $ filtrado con solo tipos de fruta.
array_map () también crea una nueva matriz, pero a diferencia de array_filter (), la matriz resultante contiene todos los elementos de la entrada $ filtrada pero con valores alterados, debido a la aplicación de una devolución de llamada a cada elemento, de la siguiente manera:
código en vivo aquí
El código en este caso aplica una devolución de llamada utilizando el strtoupper incorporado () pero una función definida por el usuario es otra opción viable también. La devolución de llamada se aplica a cada elemento de $ filtrado y, por lo tanto, genera $ nu cuyos elementos contienen valores en mayúscula.
En el siguiente fragmento, array walk () atraviesa $ nu y realiza cambios en cada elemento con respecto al operador de referencia '&'. Los cambios ocurren sin crear una matriz adicional. El valor de cada elemento cambia en su lugar en una cadena más informativa que especifica su clave, categoría y valor.
Ver demo
Nota: la función de devolución de llamada con respecto a array_walk () toma dos parámetros que adquirirán automáticamente el valor de un elemento y su clave y, en ese orden, también cuando se invoque mediante array_walk (). (Ver más aquí ).
fuente
$lambda
y$callback
son solo expansiones eta de funciones existentes, y por lo tanto son completamente redundantes. Puede obtener el mismo resultado al pasar (el nombre de) la función subyacente:$filtered = array_filter($array, 'ctype_alpha');
y$nu = array_map('strtoupper', $filtered);