Как указано в ОП :
PHP рассматривает все массивы как ассоциативные
не совсем разумно (ИМХО) писать функцию, которая проверяет, является ли массив ассоциативным . Итак, первым делом: что является ключом в массиве PHP ?
Ключ может быть либо целым числом или строкой .
Это означает, что есть 3 возможных случая:
- Случай 1. все ключи числовые / целые .
- Случай 2. все ключи являются строками .
- Случай 3. некоторые ключи являются строками , некоторые ключи являются числовыми / целыми числами .
Мы можем проверить каждый случай с помощью следующих функций.
Случай 1: все ключи числовые / целые .
Примечание : эта функция возвращает true и для пустых массивов.
//! 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: все ключи являются строками .
Примечание : эта функция возвращает true и для пустых массивов.
//! 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. некоторые ключи являются строками , некоторые ключи являются числовыми / целыми числами .
Примечание : эта функция возвращает true и для пустых массивов.
//! 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а. ключи числовые / целые , последовательные и начинающиеся с нуля .
Примечание : эта функция возвращает true и для пустых массивов.
//! 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-разрядное целое число со знаком .