Estoy usando un mapa en php así:
function func($v) {
return $v * 2;
}
$values = array(4, 6, 3);
$mapped = array_map(func, $values);
var_dump($mapped);
¿Es posible obtener el índice del valor en la función?
Además, si estoy escribiendo código que necesita el índice, ¿debería usar un bucle for en lugar de un mapa?
array_map()
un número arbitrario de argumentos :)array_keys
permanecerán en el mismo orden que en la matriz original. Por lo tanto, podría terminar asignando claves a valores incorrectos. El enfoque seguro es usar soloarray_keys
como segundo argumento dearray_map
y luego pasar la matriz al cierre con lause
declaración.Al mapear una función anónima sobre una matriz anónima, no hay forma de acceder a las claves:
array_map( function($val) use ($foo) { /* ... */ }, array(key1 => val1, key2 => val2, /* ... */));
array_reduce tampoco tiene acceso a las claves. array_walk puede acceder a las claves, pero la matriz se pasa por referencia, lo que requiere una capa de indirección.
Algunas soluciones son:
Matriz de pares
Esto es malo, ya que estamos cambiando la matriz original. Además, las llamadas repetitivas "array ()" aumentan linealmente con la longitud de la matriz:
array_map( function($pair) use ($foo) { list($key, $val) = $pair; /* ... */ }, array(array(key1, val1), array(key2, val2), /* ... */));
Variable temporal
Estamos actuando sobre la matriz original, y el texto estándar es constante, pero podemos golpear fácilmente una variable existente:
$i_hope_this_does_not_conflict = array(key1 => val1, key2 => val2, /* ... */); array_map( function($key, $val) use ($foo) { /* ... */ }, array_keys($i_hope_this_does_not_conflict), $i_hope_this_does_not_conflict); unset($i_hope_this_does_not_conflict);
Función de disparo único
Podemos usar el alcance de la función para evitar aplastar los nombres existentes, pero tenemos que agregar una capa adicional de "uso":
call_user_func( function($arr) use ($foo) { return array_map(function($key, $val) use ($foo) { /* ... */ }, array_keys($arr), $arr); }, array(key1 => val1, key2 => val2, /* ... */));
Función one-shot de múltiples argumentos
Definimos la función que estamos mapeando en el alcance original para evitar el "uso" repetitivo):
call_user_func( function($f, $arr) { return array_map($f, array_keys($arr), $arr); }, function($key, $val) use ($foo) { /* ... */ }, array(key1 => val1, key2 => val2, /* ... */));
Nueva función
Lo interesante a tener en cuenta es que nuestra última función one-shot tiene una bonita firma genérica y se parece mucho a array_map. Es posible que queramos darle un nombre y reutilizarlo:
function array_mapk($f, $arr) { return array_map($f, array_keys($arr), $arr); }
Nuestro código de aplicación se convierte en:
array_mapk( function($key, $val) use ($foo) { /* ... */ }, array(key1 => val1, key2 => val2, /* ... */));
Paseo indirecto por matriz
Al escribir lo anterior, ignoré array_walk ya que requiere que su argumento se pase por referencia; sin embargo, desde entonces me di cuenta de que es fácil solucionar esto usando call_user_func. Creo que esta es la mejor versión hasta ahora:
call_user_func( 'array_walk', array(key1 => val1, key2 => val2, /* ... */), function($val, $key) use ($foo) { /* ... */ });
fuente
Muy simple:
Solo función array_map: ¡no tiene clave de índice!
$params = [4,6,2,11,20]; $data = array_map(function($v) { return ":id{$v}";}, $params); array (size=5) 0 => string ':id4' (length=4) 1 => string ':id6' (length=4) 2 => string ':id2' (length=4) 3 => string ':id11' (length=5) 4 => string ':id20' (length=5)
Ahora, combine con array_keys:
$data = array_map( function($k) use ($params) { return ":id{$k}_${params[$k]}"; }, array_keys($params) ); array (size=5) 0 => string ':id0_4' (length=6) 1 => string ':id1_6' (length=6) 2 => string ':id2_2' (length=6) 3 => string ':id3_11' (length=7) 4 => string ':id4_20' (length=7)
fuente