15 вопросов
Массив в PHP - это упорядоченная хеш-таблица. Внутренняя структура (HashTable) содержит:
Это гибрид массива и хеш-таблицы: поддерживает числовые индексы (как массив) и строковые ключи (как map/dict). Порядок элементов всегда сохраняется (в отличие от HashMap в Java или map в Go).
Сложность операций: доступ по ключу O(1) amortized, добавление O(1) amortized, поиск по значению O(n).
Технически это один и тот же тип array, разница только в ключах:
// Индексированный - числовые ключи (0, 1, 2...)
$fruits = ['apple', 'banana', 'cherry'];
// Ассоциативный - строковые ключи
$user = ['name' => 'John', 'age' => 30];
// Смешанный (допускается, но не рекомендуется)
$mixed = [0 => 'zero', 'key' => 'value', 1 => 'one'];Функция array_is_list() (PHP 8.1) проверяет, является ли массив списком (последовательные числовые ключи от 0).
SplFixedArray - массив фиксированного размера с числовыми индексами. Использует на 30-50% меньше памяти, чем обычный array:
$arr = new SplFixedArray(1000);
$arr[0] = 'hello';
$arr[999] = 'world';
// $arr[1000] - OutOfRangeException
$arr->setSize(2000); // можно изменить размерЭффективнее обычного массива когда: большой массив (10K+ элементов), только числовые индексы, не нужны ассоциативные операции (array_filter, array_map). Для обычных задач стандартный array предпочтительнее из-за гибкости.
По значению, но с оптимизацией copy-on-write:
function process(array $arr) {
// $arr - "копия", но реально данные не скопированы (COW)
$arr[] = 'new'; // ЗДЕСЬ происходит реальное копирование
}
$data = [1, 2, 3];
process($data);
var_dump($data); // [1, 2, 3] - не изменилсяДля передачи по ссылке:
function addItem(array &$arr) {
$arr[] = 'new'; // изменяет оригинал
}COW делает передачу по значению эффективной для чтения - копия создается только при модификации.
При передаче по значению (по умолчанию) - изменения не видны снаружи:
function modify(array $arr) {
$arr[0] = 'changed';
}
$data = ['original'];
modify($data);
echo $data[0]; // "original"При передаче по ссылке - изменения видны:
function modify(array &$arr) {
$arr[0] = 'changed';
}
$data = ['original'];
modify($data);
echo $data[0]; // "changed"В момент модификации массива, переданного по значению, срабатывает copy-on-write: PHP создает полную копию массива и модифицирует ее.
// Трансформация
array_map(fn($x) => $x * 2, [1, 2, 3]); // [2, 4, 6]
array_filter([0, 1, '', 'a'], fn($x) => $x); // [1 => 1, 3 => 'a']
array_reduce([1,2,3], fn($c, $x) => $c + $x, 0); // 6
// Объединение
array_merge($a, $b); // перенумеровывает числовые ключи
$a + $b; // сохраняет ключи первого
array_combine($keys, $vals);
// Сравнение
array_diff($a, $b); // элементы из $a, которых нет в $b
array_intersect($a, $b); // общие элементы
// Поиск
in_array($val, $arr, true); // true = строгое сравнение
array_search($val, $arr);
array_key_exists('key', $arr);
// Извлечение
array_column($users, 'name'); // столбец из 2D массива
array_slice($arr, 1, 3);
array_unique($arr);$arr = [3, 1, 2];
sort($arr); // по значению, сбрасывает ключи: [1, 2, 3]
rsort($arr); // обратная сортировка
asort($arr); // по значению, сохраняет ключи
arsort($arr); // обратная с сохранением ключей
ksort($arr); // по ключам
krsort($arr); // по ключам, обратная
// Пользовательская сортировка
usort($arr, fn($a, $b) => $a <=> $b); // spaceship operator
uasort($arr, $callback); // с сохранением ключей
uksort($arr, $callback); // по ключам
// Многополевая
array_multisort($col1, SORT_ASC, $col2, SORT_DESC, $arr);Все функции сортируют массив in-place (модифицируют оригинал). Используют алгоритм Quicksort. Spaceship оператор <=> (PHP 7) возвращает -1, 0 или 1.
// Кодирование
$json = json_encode(['name' => 'John', 'age' => 30]);
// '{"name":"John","age":30}'
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
// Декодирование
$data = json_decode($json, true); // true = ассоциативный массив
$obj = json_decode($json); // объект stdClass
// Проверка ошибок
if (json_last_error() !== JSON_ERROR_NONE) {
echo json_last_error_msg();
}
// PHP 8.3
json_validate($json); // быстрая проверка без декодированияВажно: json_encode() возвращает false при ошибке. Флаг JSON_THROW_ON_ERROR (PHP 7.3) превращает ошибки в исключения.
// list() - классический синтаксис
list($a, $b, $c) = [1, 2, 3];
// Короткий синтаксис (PHP 7.1+)
[$a, $b, $c] = [1, 2, 3];
// Пропуск элементов
[, $second] = [1, 2, 3]; // $second = 2
// С ассоциативными ключами (PHP 7.1+)
['name' => $name, 'age' => $age] = ['name' => 'John', 'age' => 30];
// В foreach
$users = [['John', 30], ['Jane', 25]];
foreach ($users as [$name, $age]) {
echo "$name is $age";
}
// Вложенная деструктуризация
[[$a, $b], [$c, $d]] = [[1, 2], [3, 4]];// Распаковка массива (PHP 7.4+ для строковых ключей в 8.1)
$first = [1, 2, 3];
$second = [4, 5, 6];
$merged = [...$first, ...$second]; // [1, 2, 3, 4, 5, 6]
// В вызове функции
function sum(int ...$nums): int {
return array_sum($nums);
}
$args = [1, 2, 3];
echo sum(...$args); // 6
// Ассоциативные массивы (PHP 8.1+)
$defaults = ['color' => 'red', 'size' => 'M'];
$custom = ['color' => 'blue'];
$result = [...$defaults, ...$custom]; // color=blue, size=M// compact() - создает массив из переменных
$name = 'John';
$age = 30;
$data = compact('name', 'age');
// ['name' => 'John', 'age' => 30]
// extract() - создает переменные из массива
$data = ['name' => 'John', 'age' => 30];
extract($data);
echo $name; // "John"
echo $age; // 30extract() считается опасным - может перезаписать существующие переменные, создает неявные зависимости. Используйте с EXTR_SKIP или EXTR_PREFIX для безопасности. В современном PHP лучше использовать деструктуризацию.
SPL структуры данных, реализованные на C (эффективнее массивов для специфичных задач):
// Стек (LIFO)
$stack = new SplStack();
$stack->push('a');
$stack->push('b');
echo $stack->pop(); // 'b'
// Очередь (FIFO)
$queue = new SplQueue();
$queue->enqueue('a');
$queue->enqueue('b');
echo $queue->dequeue(); // 'a'
// Приоритетная очередь
$pq = new SplPriorityQueue();
$pq->insert('low', 1);
$pq->insert('high', 10);
echo $pq->extract(); // 'high'
// Куча (MinHeap/MaxHeap)
$heap = new SplMinHeap();
$heap->insert(3);
$heap->insert(1);
echo $heap->extract(); // 1$arr = ['a', 'b', 'c', 'd'];
// unset - удаляет, НЕ перенумеровывает ключи
unset($arr[1]);
// [0 => 'a', 2 => 'c', 3 => 'd'] (дырка в индексах!)
// array_splice - удаляет и перенумеровывает
$arr = ['a', 'b', 'c', 'd'];
array_splice($arr, 1, 1);
// ['a', 'c', 'd'] (индексы 0, 1, 2)
// Удаление по значению
$arr = array_values(array_diff($arr, ['c']));
// array_filter для условного удаления
$arr = array_values(array_filter($arr, fn($x) => $x !== 'c'));После unset() используйте array_values() для перенумерации, если нужны последовательные индексы.
$arr = ['key' => null, 'other' => 'value'];
// isset() - false для null значений!
isset($arr['key']); // false (значение null)
isset($arr['other']); // true
isset($arr['missing']); // false
// array_key_exists() - проверяет только ключ
array_key_exists('key', $arr); // true
array_key_exists('missing', $arr); // falseЕсли ключ может содержать null как допустимое значение - используйте array_key_exists(). Для большинства случаев isset() быстрее и предпочтительнее. Null coalescing: $val = $arr['key'] ?? 'default'.
Генераторы позволяют обрабатывать данные по одному элементу, не загружая все в память:
// Обычный массив - 1 млн элементов в памяти
function getAll(): array {
$data = [];
for ($i = 0; $i < 1_000_000; $i++) {
$data[] = $i;
}
return $data; // ~32 MB
}
// Генератор - 1 элемент в памяти
function getAll(): Generator {
for ($i = 0; $i < 1_000_000; $i++) {
yield $i;
}
}
foreach (getAll() as $item) {
process($item);
}Генераторы идеальны для: чтения больших файлов, результатов из БД, потоковой обработки. Потребление памяти не зависит от объема данных.