Как проверить, является ли массив в PHP ассоциативным или последовательным (индексированным)?
Основная идея: что значит «последовательный» массив?
В PHP нет встроенной функции для такой проверки, поэтому разработчики придумывают свои решения. Главное — чётко определить, что вы считаете «последовательным» массивом. Обычно под этим понимают массив, у которого все ключи — целые числа, и они идут по порядку от 0 до N-1 (где N — количество элементов). Ассоциативный массив — это любой массив, у которого хотя бы один ключ не является целым числом или нарушена последовательность.
Самый надёжный и производительный способ
Лучший подход — проверить два условия:
- Все ключи — целые числа (не строки, не float).
- Ключи образуют строгую последовательность 0, 1, 2, ..., count($array)-1.
Вот реализация:
function isSequentialArray(array $array): bool {
if (empty($array)) {
// Пустой массив можно считать и тем, и другим — зависит от задачи
// Обычно возвращают true (последовательный) или false
return true;
}
// Проверяем, что все ключи — целые числа
$keys = array_keys($array);
foreach ($keys as $key) {
if (!is_int($key)) {
return false; // Нашли строковый ключ — ассоциативный
}
}
// Проверяем, что ключи идут по порядку от 0 до count-1
return $keys === range(0, count($array) - 1);
}
// Примеры:
$sequential = [10, 20, 30]; // 0,1,2 — true
$assoc = ['a' => 1, 'b' => 2]; // строковые ключи — false
$mixed = [0 => 'x', 2 => 'y']; // числовые, но не по порядку — false
$startFromOne = [1 => 'a', 2 => 'b']; // начинается с 1 — false
$stringNumeric = ['0' => 'test']; // ключ — строка '0', а не int — false
var_dump(isSequentialArray($sequential)); // true
var_dump(isSequentialArray($assoc)); // false
var_dump(isSequentialArray($mixed)); // false
var_dump(isSequentialArray($startFromOne)); // false
var_dump(isSequentialArray($stringNumeric)); // false
Почему это лучший вариант?
- Проверка типов:
is_int($key)отсекает строковые ключи, даже если они выглядят как числа (например,'0'). - Проверка последовательности: сравнение с
range()гарантирует, что ключи идут строго по порядку без пропусков. - Производительность: функция работает за O(n), где n — количество ключей. Для большинства массивов это оптимально.
- Гибкость: легко изменить логику для других критериев (например, считать последовательным массив с ключами 0,5,10? Тогда уберите проверку range).
Альтернативный однострочник (менее надёжный)
Многие используют array_values() и сравнивают с исходным массивом:
function isSequentialArray(array $array): bool {
return $array === array_values($array);
}
Этот метод работает, но не проверяет типы ключей. Если у вас есть ключ-строка '0', array_values() преобразует его в целое число, и массив может ошибочно считаться последовательным. Используйте его только если уверены, что все ключи уже целые числа.
Заключение
Для 99% случаев используйте первый вариант с проверкой типов и range. Если вам нужно просто проверить, является ли массив «списком» (без строгих требований к порядку ключей), можно упростить проверку, убрав сравнение с range. Главное — понимать, какие данные вы ожидаете на входе.
<<Альтернативный подход: использование array_diff_key()
Если вам не нужно различать пустые массивы или вы работаете с большими объёмами данных, можно использовать более лаконичный метод с функциями array_keys() и array_filter():
function isAssociative(array $array): bool {
// Если массив пуст — считаем его не ассоциативным (или наоборот)
if (empty($array)) return false;
// Проверяем, есть ли хотя бы один нечисловой ключ
return count(array_filter(array_keys($array), 'is_string')) > 0;
}
// Пример:
$assoc = ['name' => 'John', 'age' => 30];
$seq = [1, 2, 3];
var_dump(isAssociative($assoc)); // true
var_dump(isAssociative($seq)); // false
Этот метод проверяет только наличие строковых ключей. Если массив имеет числовые ключи, но не по порядку (например, [0 => 'a', 5 => 'b']), он будет считаться последовательным. Это может быть полезно, если вас интересует только «ассоциативность» (наличие строковых ключей), а не строгая последовательность.
Когда использовать?
- Если вы работаете с JSON-данными, где ключи всегда строки.
- Если вам нужно быстро отличить «список» от «словаря» без строгих требований к порядку.
- Для обратной совместимости со старым кодом.
Недостаток: функция не различает массивы с пропущенными числовыми ключами (например, [0 => 'a', 2 => 'b'] будет считаться последовательным). Если это критично — используйте первый ответ.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги