Як зазначено в ОП :
PHP розглядає всі масиви як асоціативні
не зовсім розумно (IMHO) писати функцію, яка перевіряє, чи масив асоціативний . Тож спочатку перше: що є ключем у масиві PHP ?:
Ключ може бути або цілим числом або рядком .
Це означає, що є 3 можливі випадки:
- Випадок 1. усі ключі є числовими / цілими числами .
- Справа 2. усі клавіші - це рядки .
- Випадок 3. деякі клавіші - це рядки , деякі - числові / цілі числа .
Ми можемо перевірити кожен випадок за допомогою наступних функцій.
Випадок 1: всі ключі є числовими / цілими числами .
Примітка . Ця функція повертає істину і для порожніх масивів.
//! 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);
}
Випадок 2: усі клавіші - це рядки .
Примітка . Ця функція повертає істину і для порожніх масивів.
//! 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);
}
Випадок 3. деякі клавіші - це рядки , деякі - числові / цілі числа .
Примітка . Ця функція повертає істину і для порожніх масивів.
//! 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;
}
Звідси випливає, що:
Тепер, щоб масив був "справжнім" масивом, до якого ми всі звикли, це означає:
- Її ключами є всі числові / цілі числа .
- Його клавіші є послідовними (тобто збільшуються на кроці 1).
- Його клавіші починаються з нуля .
Ми можемо перевірити за допомогою наступної функції.
Випадок 3а. ключі є числовими / цілими числами , послідовними та нульовими .
Примітка . Ця функція повертає істину і для порожніх масивів.
//! 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);
}
Застереження / підводні камені (або, навіть, більш своєрідні факти про ключі масиву в PHP)
Цілі ключі
Ключами цих масивів є цілі числа :
array(0 => "b");
array(13 => "b");
array(-13 => "b"); // Negative integers are also integers.
array(0x1A => "b"); // Hexadecimal notation.
Строкові клавіші
Ключами цих масивів є рядки :
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!
Цілі клавіші, схожі на рядки
Якщо ви вважаєте , що ключ в array("13" => "b")
це рядок , то ви помиляєтеся . З документа тут :
Рядки, що містять дійсні цілі числа, будуть передані цілому типу. Наприклад, ключ "8" буде фактично зберігатися під 8. З іншого боку, "08" не буде передано, оскільки це не є дійсним десятковим цілим числом.
Наприклад, ключовими для цих масивів є цілі числа :
array("13" => "b");
array("-13" => "b"); // Negative, ok.
Але ключовим для цих масивів є рядки :
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.
Більше того, за словами доктора ,
Розмір цілого числа залежить від платформи, хоча максимальне значення близько двох мільярдів - це звичайне значення (це 32 біти підписано). 64-бітні платформи зазвичай мають максимальне значення близько 9E18, за винятком Windows, яка завжди 32-бітна. PHP не підтримує непідписані цілі числа.
Отже, ключ для цього масиву може бути, а не може бути цілим числом - це залежить від вашої платформи.
array("60000000000" => "b"); // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.
Ще гірше, PHP має тенденцію бути помилковою, якщо ціле число знаходиться поблизу межі 2 31 = 2,147,483,648 (див. Помилка 51430 , помилка 52899 ). Наприклад, у моєму локальному середовищі (PHP 5.3.8 на XAMPP 1.7.7 в Windows 7), var_dump(array("2147483647" => "b"))
дає
array(1) {
[2147483647]=>
string(1) "b"
}
але на цій демонстраційній версії на кодовій панелі (PHP 5.2.5) дається те саме вираз
array(1) {
["2147483647"]=>
string(1) "b"
}
Таким чином, ключ є цілим числом в одному середовищі, а рядок в іншому, хоча 2147483647
це дійсне підписане 32-бітове ціле число .