Jak stwierdził PO :
PHP traktuje wszystkie tablice jako asocjacyjne
napisanie funkcji, która sprawdza, czy tablica jest asocjacyjna, nie jest rozsądne (IMHO) . Po pierwsze: co jest kluczem w tablicy PHP ?:
Klucz może być albo całkowitą lub ciąg .
Oznacza to, że są 3 możliwe przypadki:
- Przypadek 1. wszystkie klucze są liczbami / liczbami całkowitymi .
- Przypadek 2. wszystkie klucze są ciągami znaków .
- Przypadek 3. niektóre klucze są ciągami , niektóre klucze są liczbami / liczbami całkowitymi .
Możemy sprawdzić każdy przypadek za pomocą następujących funkcji.
Przypadek 1: wszystkie klucze są liczbami / liczbami całkowitymi .
Uwaga : Ta funkcja zwraca wartość true również dla pustych tablic.
//! 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);
}
Przypadek 2: wszystkie klucze są ciągami znaków .
Uwaga : Ta funkcja zwraca wartość true również dla pustych tablic.
//! 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);
}
Przypadek 3. niektóre klucze są ciągami , niektóre klucze są liczbami / liczbami całkowitymi .
Uwaga : Ta funkcja zwraca wartość true również dla pustych tablic.
//! 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;
}
Wynika, że:
Teraz, aby tablica była „prawdziwą” tablicą, do której wszyscy jesteśmy przyzwyczajeni, co oznacza:
- Jej klawisze są wszystkie liczbowe / całkowitymi .
- Jego klucze są sekwencyjne (tzn. Zwiększane o krok 1).
- Jego klucze zaczynają się od zera .
Możemy to sprawdzić za pomocą następującej funkcji.
Przypadek 3a klucze są liczbowe / całkowite , sekwencyjne i zerowe .
Uwaga : Ta funkcja zwraca wartość true również dla pustych tablic.
//! 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);
}
Ostrzeżenia / pułapki (lub jeszcze bardziej osobliwe fakty na temat kluczy tablic w PHP)
Klucze całkowite
Kluczami dla tych tablic są liczby całkowite :
array(0 => "b");
array(13 => "b");
array(-13 => "b"); // Negative integers are also integers.
array(0x1A => "b"); // Hexadecimal notation.
Klucze strunowe
Kluczami do tych tablic są ciągi znaków :
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!
Klucze całkowite, które wyglądają jak łańcuchy
Jeśli uważasz, że klucz array("13" => "b")
jest ciągiem , jesteś w błędzie . Z dokumentu tutaj :
Ciągi zawierające prawidłowe liczby całkowite zostaną rzutowane na typ całkowity. Np. Klucz „8” faktycznie będzie przechowywany pod 8. Z drugiej strony „08” nie zostanie rzucony, ponieważ nie jest to poprawna liczba dziesiętna.
Na przykład kluczem do tych tablic są liczby całkowite :
array("13" => "b");
array("-13" => "b"); // Negative, ok.
Ale kluczem do tych tablic są ciągi :
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.
Co więcej, zgodnie z dokumentem ,
Rozmiar liczby całkowitej zależy od platformy, chociaż maksymalna wartość wynosząca około dwóch miliardów jest zwykle wartością (to 32 bitów ze znakiem). Platformy 64-bitowe zwykle mają maksymalną wartość około 9E18, z wyjątkiem systemu Windows, który zawsze jest 32-bitowy. PHP nie obsługuje liczb całkowitych bez znaku.
Tak więc kluczem do tej tablicy może być lub nie być liczbą całkowitą - to zależy od platformy.
array("60000000000" => "b"); // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.
Co gorsza, PHP ma tendencję do błędów, jeśli liczba całkowita znajduje się w pobliżu granicy 2 31 = 2 147 483 648 (patrz błąd 51430 , błąd 52899 ). Na przykład w moim lokalnym środowisku (PHP 5.3.8 na XAMPP 1.7.7 na Windows 7) var_dump(array("2147483647" => "b"))
daje
array(1) {
[2147483647]=>
string(1) "b"
}
ale w tej wersji demonstracyjnej na żywo na codepad (PHP 5.2.5) daje to samo wyrażenie
array(1) {
["2147483647"]=>
string(1) "b"
}
Zatem kluczem jest liczba całkowita w jednym środowisku, ale ciąg znaków w innym, mimo że 2147483647
jest to 32-bitowa liczba całkowita ze znakiem .