Las matrices en PHP, más conocidas como arrays, se construyen mediante pares clave => valor que representan cada elemento de la matriz. En función del tipo de clave, o key, el array puede ser:

  • asociativo: la clave es un string, un texto identificador, por ejemplo $array['nombre'], $array['edad'], etc.
  • secuencial: la clave es un índice numérico, de ahí que este tipo de arrays también se conozcan como arrays indexados, por ejemplo, $array[1], $array[2], etc.

La representación interna en PHP de ambos tipos de arrays es la misma, un mapa con claves y valores asociados con un orden específico, pero, aún así, en algunas situaciones podemos necesitar conocer si estamos ante uno u otro tipo.

PHP ofrece varias funciones internas para comprobar el tipo de datos, pero ninguna para diferenciar “tipos” de arrays, porque, como hemos dicho en el párrafo anterior, ambos tipos son representados de la misma forma por PHP.

Uno de los métodos más populares y sencillos se basa en comparar las keys de un array con el resultado que de la función range() desde 0 al número de elementos del array. Así, podríamos comprobar si un array es asociativo (las claves son strings) o secuenciales (las claves son un índice numérico) de la siguiente forma:

function is_assoc( $array ) {
	return array_keys( $array ) !== range( 0, count($array) - 1 );
}

Supongamos que un array tiene 5 elementos. El planteamiento de esta función anterior sería: si range(0, 4) me devuelve el mismo valor que array_keys($array), estaré ante un array secuencial, de lo contrario estoy ante un array asociativo (vea manual de range() y array_keys()).

Problema: definición de array secuencial

Según la definición de array secuencial que hemos dado antes, y que es la más extendida, las claves de un array secuencial forman un índice numérico que va desde 0 (cero) hasta el número de elementos menos 1. En PHP, este índice numérico secuencial se genera si no se especifican los índices o si se especifican con estos valores:

// Los tres arrays son secuenciales
// y se consideran iguales en PHP
$datos1 = [
            "Gato",
            "Perro",
            "Jirafa"
        ];
$datos2 = [
            0 => "Gato",
            1 => "Perro",
            2 => "Jirafa"
        ];
$datos3 = [
            "0" => "Gato",
            "1" => "Perro",
            "2" => "Jirafa"
        ];

Los tres arrays anteriores son iguales y se considerarían secuenciales, sus claves son 0, 1 y 2, y se puede acceder al valor de cada elemento mediante $datos[indice], donde índice es el número que representa el key.

Pero fíjate que en los ejemplos anteriores podemos especificar el número de índice a nuestro antojo, ¿que pasa si el key menor no es 0? (2, 3, 4, …) ¿Y si hay “huecos”? (2, 8, 54,…). En estos casos la solución propuesta con range() y array_keys() tratará los datos como array asociativo y para muchos programadores estos arrays seguirían siendo secuenciales.

Y es que no hay una definición estándar de array secuencial, algo normal si recordamos que cualquier array es representado y tratado de la misma forma por PHP.

Para algunos, un array en el que todas las claves son números enteros, aunque no comiencen por cero o no sigan la secuencia +1, es un array secuencial. Para otros, un array en el que todas las claves sean numéricas pero en el que el valor de la clave es importante, se convierte automáticamente en array asociativo aunque todas claves sean numéricas.

Por ejemplo, si tenemos un array con claves numéricas no secuenciales:

[6 => 'rojo', 4 => 'verde', 8 => 'amarillo']

En este caso, el valor de las claves es importante para diferenciar cada elemento del array. Al ser todas las claves numéricas, unos dirían que es un array secuencial, pero como el valor de las claves es importante, otros dirían que es asociativo. Para otros, sin embargo, hacer esta distinción es irrelevante y adoptan otro tipo de lógica durante el desarrollo de un programa.

Además, hay que tener en cuenta que en PHP las claves tipo string que contienen representación literal de enteros son convertidas a datos tipo integer. Por ejemplo, la clave "8" (string) es convertida a 8 (integer), pero "08" si es tratado como string y no es convertido a 8.

Lo mismo ocurre si las claves tiene un valor tipo float, también son transformadas al tipo integer. Por ejemplo, si el valor de una clave es igual a 8.5 (float), el valor es transformado a 8, pero "8.5" (string) quedaría igual.

En otras palabras, en PHP no puedes diferenciar el key "8" (texto) del key 8 (número). (vea la documentación sobre arrays).

En cualquier caso, si quieres interpretar como secuencial cualquier array cuyas claves sean todas números enteros o strings con representación de enteros, sin importar que la menor no sea cero o que haya huecos entre ellas, puedes utilizar la siguiente función:

function is_assoc( $array ) {

     foreach(array_keys($array) as $key) {
         if (!is_int($key)) return true;
     }

     return false;

}

La función anterior comprueba cada una de las claves del array hasta que encuentre una que no sea un número entero o una representación literal de entero; sólo en ese caso devolverá true, indicando que el array es asociativo. En caso contrario devolverá false, indicando que el array es secuencial o indexado.