Como lo indica el OP :
PHP trata todas las matrices como asociativas
no es del todo razonable (en mi humilde opinión) escribir una función que verifique si una matriz es asociativa . Entonces, primero lo primero: ¿qué es una clave en una matriz PHP ?
La clave puede ser un número entero o una cadena .
Eso significa que hay 3 casos posibles:
- Caso 1. todas las claves son numéricas / enteras .
- Caso 2. todas las claves son cadenas .
- Caso 3. algunas teclas son cadenas , algunas teclas son numéricas / enteras .
Podemos verificar cada caso con las siguientes funciones.
Caso 1: todas las claves son numéricas / enteras .
Nota : Esta función también devuelve verdadero para matrices vacías.
//! Check whether the input is an array whose keys are all integers.
/*!
\param[in] $InputArray (array) Input array.
\return (bool) \b true iff the input is an array whose keys are all integers.
*/
function IsArrayAllKeyInt($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return array_unique(array_map("is_int", array_keys($InputArray))) === array(true);
}
Caso 2: todas las teclas son cadenas .
Nota : Esta función también devuelve verdadero para matrices vacías.
//! Check whether the input is an array whose keys are all strings.
/*!
\param[in] $InputArray (array) Input array.
\return (bool) \b true iff the input is an array whose keys are all strings.
*/
function IsArrayAllKeyString($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return array_unique(array_map("is_string", array_keys($InputArray))) === array(true);
}
Caso 3. algunas teclas son cadenas , algunas teclas son numéricas / enteras .
Nota : Esta función también devuelve verdadero para matrices vacías.
//! Check whether the input is an array with at least one key being an integer and at least one key being a string.
/*!
\param[in] $InputArray (array) Input array.
\return (bool) \b true iff the input is an array with at least one key being an integer and at least one key being a string.
*/
function IsArraySomeKeyIntAndSomeKeyString($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return count(array_unique(array_map("is_string", array_keys($InputArray)))) >= 2;
}
Resulta que:
Ahora, para que una matriz sea una matriz "genuina" a la que todos estamos acostumbrados, lo que significa:
- Sus claves son todas numéricas / enteras .
- Sus claves son secuenciales (es decir, aumentan en el paso 1).
- Sus claves comienzan desde cero .
Podemos verificar con la siguiente función.
Caso 3a. Las teclas son numéricas / enteras , secuenciales y de base cero .
Nota : Esta función también devuelve verdadero para matrices vacías.
//! Check whether the input is an array whose keys are numeric, sequential, and zero-based.
/*!
\param[in] $InputArray (array) Input array.
\return (bool) \b true iff the input is an array whose keys are numeric, sequential, and zero-based.
*/
function IsArrayKeyNumericSequentialZeroBased($InputArray)
{
if(!is_array($InputArray))
{
return false;
}
if(count($InputArray) <= 0)
{
return true;
}
return array_keys($InputArray) === range(0, count($InputArray) - 1);
}
Advertencias / trampas (o, hechos aún más peculiares sobre las claves de matriz en PHP)
Teclas enteras
Las claves para estas matrices son enteros :
array(0 => "b");
array(13 => "b");
array(-13 => "b"); // Negative integers are also integers.
array(0x1A => "b"); // Hexadecimal notation.
Teclas de cadena
Las claves para estas matrices son cadenas :
array("fish and chips" => "b");
array("" => "b"); // An empty string is also a string.
array("stackoverflow_email@example.com" => "b"); // Strings may contain non-alphanumeric characters.
array("stack\t\"over\"\r\nflow's cool" => "b"); // Strings may contain special characters.
array('$tα€k↔øv∈rflöw⛄' => "b"); // Strings may contain all kinds of symbols.
array("functіon" => "b"); // You think this looks fine? Think again! (see https://stackoverflow.com/q/9246051/1402846)
array("ま말轉转ДŁ" => "b"); // How about Japanese/Korean/Chinese/Russian/Polish?
array("fi\x0sh" => "b"); // Strings may contain null characters.
array(file_get_contents("https://www.google.com/images/nav_logo114.png") => "b"); // Strings may even be binary!
Teclas enteras que parecen cuerdas
Si cree que la clave array("13" => "b")
es una cadena , está equivocado . Del documento aquí :
Las cadenas que contienen enteros válidos se convertirán al tipo entero. Por ejemplo, la clave "8" se almacenará realmente en 8. Por otro lado, "08" no se lanzará, ya que no es un entero decimal válido.
Por ejemplo, la clave para estas matrices son enteros :
array("13" => "b");
array("-13" => "b"); // Negative, ok.
Pero la clave para estas matrices son las cadenas :
array("13." => "b");
array("+13" => "b"); // Positive, not ok.
array("-013" => "b");
array("0x1A" => "b"); // Not converted to integers even though it's a valid hexadecimal number.
array("013" => "b"); // Not converted to integers even though it's a valid octal number.
array("18446744073709551616" => "b"); // Not converted to integers as it can't fit into a 64-bit integer.
Además, según el documento ,
El tamaño de un número entero depende de la plataforma, aunque un valor máximo de aproximadamente dos mil millones es el valor habitual (es decir, 32 bits con signo). Las plataformas de 64 bits generalmente tienen un valor máximo de aproximadamente 9E18, excepto Windows, que siempre es de 32 bits. PHP no admite enteros sin signo.
Por lo tanto, la clave para esta matriz puede o no ser un número entero ; depende de su plataforma.
array("60000000000" => "b"); // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.
Peor aún, PHP tiende a ser errores si el número entero está cerca del límite 2 31 = 2,147,483,648 (ver error 51430 , error 52899 ). Por ejemplo, en mi entorno local (PHP 5.3.8 en XAMPP 1.7.7 en Windows 7), var_dump(array("2147483647" => "b"))
da
array(1) {
[2147483647]=>
string(1) "b"
}
pero en esta demostración en vivo en el teclado (PHP 5.2.5), la misma expresión da
array(1) {
["2147483647"]=>
string(1) "b"
}
Entonces la clave es un número entero en un entorno pero una cadena en otro, aunque 2147483647
es un número entero de 32 bits con signo válido .