Conforme declarado pelo OP :
PHP trata todas as matrizes como associativas
não é muito sensato (IMHO) escrever uma função que verifique se uma matriz é associativa . Então, a primeira coisa: o que é uma chave em uma matriz PHP ?
A chave pode ser um número inteiro ou uma sequência de caracteres .
Isso significa que existem três casos possíveis:
- Caso 1. todas as teclas são numéricas / inteiras .
- Caso 2. todas as chaves são cadeias de caracteres .
- Caso 3. algumas chaves são seqüências de caracteres , outras são numéricas / números inteiros .
Podemos verificar cada caso com as seguintes funções.
Caso 1: todas as teclas são numéricas / inteiras .
Nota : Esta função também retorna true para matrizes vazias.
//! 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 as chaves são cadeias de caracteres .
Nota : Esta função também retorna true para matrizes vazias.
//! 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. algumas chaves são seqüências de caracteres , outras são numéricas / números inteiros .
Nota : Esta função também retorna true para matrizes vazias.
//! 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;
}
Segue que:
Agora, para uma matriz ser uma matriz "genuína" à qual estamos acostumados, o que significa:
- Suas teclas são todas numéricas / inteiras .
- Suas teclas são seqüenciais (ou seja, aumentam na etapa 1).
- Suas teclas começam do zero .
Podemos verificar com a seguinte função.
Caso 3a. As teclas são numéricas / inteiras , seqüenciais e baseadas em zero .
Nota : Esta função também retorna true para matrizes vazias.
//! 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);
}
Advertências / Armadilhas (ou, fatos ainda mais peculiares sobre chaves de array em PHP)
Chaves inteiras
As chaves para essas matrizes são números inteiros :
array(0 => "b");
array(13 => "b");
array(-13 => "b"); // Negative integers are also integers.
array(0x1A => "b"); // Hexadecimal notation.
Teclas de cadeia
As chaves para essas matrizes são cadeias de caracteres :
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!
Chaves inteiras que se parecem com seqüências de caracteres
Se você acha que a chave array("13" => "b")
é uma string , está errado . Do documento aqui :
Sequências contendo números inteiros válidos serão convertidas para o tipo inteiro. Por exemplo, a chave "8" será realmente armazenada em 8. Por outro lado, "08" não será convertido, pois não é um número inteiro decimal válido.
Por exemplo, a chave para essas matrizes são números inteiros :
array("13" => "b");
array("-13" => "b"); // Negative, ok.
Mas a chave para essas matrizes são as strings :
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.
Além do mais, de acordo com o documento ,
O tamanho de um número inteiro depende da plataforma, embora um valor máximo de cerca de dois bilhões seja o valor usual (com 32 bits assinados). As plataformas de 64 bits geralmente têm um valor máximo de cerca de 9E18, exceto o Windows, que sempre é de 32 bits. O PHP não suporta números inteiros não assinados.
Portanto, a chave para esta matriz pode ou não ser um número inteiro - depende da sua plataforma.
array("60000000000" => "b"); // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.
Pior ainda, o PHP tende a ser buggy se o número inteiro estiver próximo do limite 2 31 = 2.147.483.648 (veja o bug 51430 , o bug 52899 ). Por exemplo, no meu ambiente local (PHP 5.3.8 no XAMPP 1.7.7 no Windows 7), var_dump(array("2147483647" => "b"))
fornece
array(1) {
[2147483647]=>
string(1) "b"
}
mas nesta demonstração ao vivo no codepad (PHP 5.2.5), a mesma expressão fornece
array(1) {
["2147483647"]=>
string(1) "b"
}
Portanto, a chave é um número inteiro em um ambiente, mas uma sequência em outro, mesmo sendo 2147483647
um número inteiro de 32 bits com sinal válido .