miércoles, 1 de septiembre de 2010

Formas de recorrer arrays con PHP

PHP dispone de múltiples estructuras para el manejo de bucles y por ende pone a nuestra disposición una serie de cómodas alternativas para recorrer y manejar arrays. Veamos unos cuantos ejemplos.

//matrizes indexadas numéricamente
$arr = range('a', 'e');
for ($i=0;$i<5;$i++) {
  echo $arr[$i];
}
//otra forma seria foreach
foreach ($arr as $letra) {
  echo $letra;
}

//matrices asociativas
$multiarr = array(
  'nombre'=>'David',
  'genero'=>'masculino',
  'edad'=>'36'
);

foreach ($multiarr as $clave=>$valor) {
  echo $clave.': '.$valor;
}
//otra forma de recorrer matrices asociativas
//es utilizando las instrucciones list() y each()
while ($el = each($multiarr)) {
  echo $el['key'].': '.$el['value'];
  //el indice key es equivalente a 0
  //y value a 1

}
//la función list() nos brinda
//la opción convertir los elementos key y value (0, 1)
//en 2 nuevas variables
while (list($clave, $valor) = each($multiarr)) {
  echo $clave.': '.$valor;
}

La función each() obliga a resetear con reset() el array una vez recorrido si lo queremos volver a utilizar.

//reubicamos el elemento actual
//al principio de la matriz
//antes de volverlo a recorrer
reset($multiarr);

Una array multidimensional es aquel que a su vez contiene en cada ubicación otras matrices. El concepto básico es similar al de una tabla con filas y columnas.

//matriz bidimensional
$arr = array(
  array('David','masculino',36),
  array('Felipe','masculino',26),
  array('Andrea','femenino',21)
);
//podemos recorrer este array utilizando
//un bucle for y un pequeño truco para
//acceder al indice mayor del array tanto
//de las filas como de las columnas
$filas = count($arr, 0);
//redondeo al alza con ceil()
$columnas = ceil(count($arr,1)/count($arr,0))-1);
echo 'Este arreglo tiene '.$filas.' filas y '.$columnas.' columnas';
for ($fil = 0; $fil < $filas; $fil++) {
  for ($col = 0; $col < $columnas; $col++) {
    echo $arr[$row][$col];
  }
}

Tal vez prefiramos almacenar los registros utilizando columnas con nombre, de nuevo echamos mano de las matrices asociativas y almacenamos el mismo conjunto de datos anterior pero con nombres en lugar de números por cada row.

$arr = array(
  array('Nombre'=>'David', 'Genero'=>'masculino', 'Edad'=>36),
  array('Nombre'=>'Felipe', 'Genero'=>'masculino', 'Edad'=>26),
  array('Nombre'=>'Andrea', 'Genero'=>'femenino', 'Edad'=>21)
);
for ($row = 0; $row < count($arr, 0); $row++) {
  foreach ($arr[$row] as $key => $value) {
    echo $key.': '.$value.'<br />';
  }
}
//o como hemos visto anteriomente
//podemos emplear list() y each() para
//asignar los distintos valores a las
//variables $key y $value para un más
//fácil manejo
for ($row = 0; $row < count($arr, 0); $row++) {
  while (list($key, $value) = each($arr[$row])) {
    echo $key.': '.$value.'<br />';
  }
}

Seguimos añadiendo dificultad a medida que vamos aumentando las dimensiones de nuestros arreglos o arrays. PHP no tiene límites en relación al número de dimensiones que podemos añadir, vamos a ver como recorreríamos un array de 3 dimensiones.

$arr = array(
  array(
    array('USER', 'David', 'masculino', 100),
    array('USER', 'Felipe', 'masculino', 26),
    array('USER', 'Andrea', 'femenino', 21)
  ),
  array(
    array('ADMIN', 'Sandra', 'femenino', 35),
    array('ADMIN', 'Pepito', 'masculino', 45),
    array('ADMIN', 'Maria', 'femenino', 19)
  ),
  array(
    array('CLIENT', 'Juan', 'masculino', 28),
    array('CLIENT', 'Olivia', 'femenino', 23),
    array('CLIENT', 'Santiago', 'masculino', 63),
    array('CLIENT', 'Vicen', 'femenino', 37)
  )
);
for ($capa = 0; $capa < count($arr, 0); $capa++) {
  echo 'Capa: ' . $capa . '<br />';
  for ($fil = 0; $fil < count($arr[$capa], 0); $fil++) {
    for ($col = 0; $col < count($arr[$capa][$fil], 0); $col++) {
      echo $arr[$capa][$fil][$col] . ' - ';
    }
    echo '<br />'; 
  } 
}

Y ya que andamos jugueteando con los arrays veamos ahora una forma de seleccionar una imagen de forma aleatoria de entre todas las que nos encontremos con la extensión jpg en un directorio dado.

$path = "img";
$d = opendir($path);
while ($img = readdir($d)) {
  if (pathinfo($path . $img, PATHINFO_EXTENSION) == 'jpg')
    $fotos[] = $img;
}
closedir($d);
shuffle($fotos);
echo "<img src=\"img/$fotos[0]\" />";

Podemos movernos o recorrer arrays con un mayor control utilizando algunas funciones específicas como each(), current(), reset(), end(), next(), pos(), prev().

Como ejemplo vamos a recorrer una matriz de forma inversa con la ayuda de end() y prev().

//situamos el puntero al final del array
$val = end($array);
//empleamos un bucle while y la función
//prev() para mover el puntero de forma inversa
while ($val) {
  echo $val;
  $val = prev($array);
}

Tenemos la posibilidad mediante array_walk() de aplicar una función personalizada a cada elemento de un array. Esto nos permite modificar o emplear cada item del arreglo de una misma forma. Esta función espera como parámetros, el array con el que trabajar, la función personalizada y opcionalmente un parámetro que pasaríamos a nuestra función.

//mostramos en pantalla el resultado
//de multiplicar cada elemento por el factor pasado
//como parámetro a nuestra función multiplicadora
$array = range(1, 10);
function multiplicador($value, $key, $factor) {
  echo $value * $factor;
}
array_walk($array, 'multiplicador', 3);