Come dichiarato dal PO :
PHP considera tutti gli array come associativi
non è del tutto sensato (IMHO) scrivere una funzione che controlla se un array è associativo . Quindi prima cosa: qual è la chiave in un array PHP ?:
La chiave può essere un numero intero o una stringa .
Ciò significa che ci sono 3 possibili casi:
- Caso 1. tutti i tasti sono numerici / interi .
- Caso 2. tutte le chiavi sono stringhe .
- Caso 3. alcune chiavi sono stringhe , alcune chiavi sono numeriche / intere .
Possiamo verificare ogni caso con le seguenti funzioni.
Caso 1: tutti i tasti sono numerici / interi .
Nota : questa funzione restituisce true anche per gli array vuoti.
//! 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: tutte le chiavi sono stringhe .
Nota : questa funzione restituisce true anche per gli array vuoti.
//! 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. alcune chiavi sono stringhe , alcune chiavi sono numeriche / intere .
Nota : questa funzione restituisce true anche per gli array vuoti.
//! 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;
}
Ne consegue che:
Ora, per un array essere un array "genuino" a cui siamo tutti abituati, nel senso che:
- Le sue chiavi sono tutte numeriche / intere .
- I suoi tasti sono sequenziali (cioè aumentano di passaggio 1).
- Le sue chiavi iniziano da zero .
Possiamo verificare con la seguente funzione.
Caso 3a le chiavi sono numeriche / intere , sequenziali e basate su zero .
Nota : questa funzione restituisce true anche per gli array vuoti.
//! 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);
}
Avvertenze / insidie (o, fatti ancora più particolari sulle chiavi dell'array in PHP)
Chiavi intere
Le chiavi per questi array sono numeri interi :
array(0 => "b");
array(13 => "b");
array(-13 => "b"); // Negative integers are also integers.
array(0x1A => "b"); // Hexadecimal notation.
Chiavi di stringa
Le chiavi per questi array sono stringhe :
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!
Tasti interi che sembrano stringhe
Se pensi che la chiave array("13" => "b")
sia una stringa , ti sbagli . Dal documento qui :
Le stringhe che contengono numeri interi validi verranno trasmesse al tipo intero. Ad esempio, la chiave "8" verrà effettivamente archiviata sotto 8. D'altra parte "08" non verrà trasmesso, in quanto non è un numero intero decimale valido.
Ad esempio, la chiave per questi array sono numeri interi :
array("13" => "b");
array("-13" => "b"); // Negative, ok.
Ma la chiave per questi array sono le stringhe :
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.
Inoltre, secondo il documento ,
La dimensione di un numero intero dipende dalla piattaforma, sebbene un valore massimo di circa due miliardi sia il valore normale (ovvero 32 bit con segno). Le piattaforme a 64 bit hanno in genere un valore massimo di circa 9E18, ad eccezione di Windows, che è sempre a 32 bit. PHP non supporta numeri interi senza segno.
Quindi la chiave per questo array può essere o meno un numero intero - dipende dalla tua piattaforma.
array("60000000000" => "b"); // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.
Ancora peggio, PHP tende a essere difettoso se il numero intero è vicino al limite 2 31 = 2.147.483.648 (vedi bug 51430 , bug 52899 ). Ad esempio, nel mio ambiente locale (PHP 5.3.8 su XAMPP 1.7.7 su Windows 7), var_dump(array("2147483647" => "b"))
dà
array(1) {
[2147483647]=>
string(1) "b"
}
ma in questa demo dal vivo su codepad (PHP 5.2.5), la stessa espressione dà
array(1) {
["2147483647"]=>
string(1) "b"
}
Quindi la chiave è un numero intero in un ambiente ma una stringa in un altro, anche se 2147483647
è un numero intero a 32 bit con segno valido .