Трансформация: array_map
<?php
declare(strict_types=1);
$numbers = [1, 2, 3, 4, 5];
// Transform each element
$doubled = array_map(fn(int $n): int => $n * 2, $numbers);
// [2, 4, 6, 8, 10]
// Keys are PRESERVED
$arr = [10 => 'a', 20 => 'b', 30 => 'c'];
$upper = array_map('strtoupper', $arr);
// [10 => 'A', 20 => 'B', 30 => 'C']
// Multiple arrays (zip)
$keys = ['name', 'age', 'city'];
$values = ['Alice', 25, 'Moscow'];
$result = array_map(null, $keys, $values);
// [['name', 'Alice'], ['age', 25], ['city', 'Moscow']]
// With null callback — creates array of arrays
$a = [1, 2, 3];
$b = ['a', 'b', 'c'];
$zipped = array_map(null, $a, $b);
// [[1, 'a'], [2, 'b'], [3, 'c']]
Запомни:
array_map()сохраняет ключи исходного массива. Callback получает только ЗНАЧЕНИЯ (не ключи). Для доступа к ключам используйтеarray_mapсarray_keysилиarray_walk.
Фильтрация: array_filter
<?php
declare(strict_types=1);
$numbers = [0, 1, 2, '', null, false, 3, '0'];
// Without callback — removes falsy values
$filtered = array_filter($numbers);
// [1 => 1, 2 => 2, 6 => 3] — keys preserved!
// With callback
$even = array_filter([1, 2, 3, 4, 5], fn(int $n): bool => $n % 2 === 0);
// [1 => 2, 3 => 4] — keys preserved!
// Reindex after filtering
$even = array_values(array_filter([1, 2, 3, 4, 5], fn(int $n): bool => $n % 2 === 0));
// [0 => 2, 1 => 4]
// Filter by keys (ARRAY_FILTER_USE_KEY)
$data = ['name' => 'Alice', 'age' => 25, '_internal' => true];
$public = array_filter(
$data,
fn(string $key): bool => !str_starts_with($key, '_'),
ARRAY_FILTER_USE_KEY
);
// ['name' => 'Alice', 'age' => 25]
// Filter by key AND value (ARRAY_FILTER_USE_BOTH)
$filtered = array_filter(
$data,
fn(mixed $value, string $key): bool => $key !== '_internal' && $value !== null,
ARRAY_FILTER_USE_BOTH
);
Ловушка экзамена:
array_filter()без callback удаляет ВСЕ falsy-значения:0,'',null,false,'0',[]. При этом ключи СОХРАНЯЮТСЯ (массив не переиндексируется).'0'является falsy и тоже будет удалена!
Сведение: array_reduce
<?php
declare(strict_types=1);
$numbers = [1, 2, 3, 4, 5];
// Sum
$sum = array_reduce($numbers, fn(int $carry, int $item): int => $carry + $item, 0);
echo $sum; // 15
// Product
$product = array_reduce($numbers, fn(int $carry, int $item): int => $carry * $item, 1);
echo $product; // 120
// Building a string
$words = ['Hello', 'World', 'PHP'];
$sentence = array_reduce(
$words,
fn(string $carry, string $word): string => $carry === '' ? $word : "$carry $word",
''
);
echo $sentence; // Hello World PHP
// Flattening nested arrays
$nested = [[1, 2], [3, 4], [5, 6]];
$flat = array_reduce($nested, fn(array $carry, array $item): array => [...$carry, ...$item], []);
// [1, 2, 3, 4, 5, 6]
array_walk
<?php
declare(strict_types=1);
// array_walk modifies array IN PLACE
$prices = ['apple' => 1.20, 'banana' => 0.50, 'cherry' => 2.00];
array_walk($prices, function (float &$price, string $name): void {
$price = round($price * 1.1, 2); // Increase by 10%
});
// $prices = ['apple' => 1.32, 'banana' => 0.55, 'cherry' => 2.2]
// With extra data
array_walk($prices, function (float &$price, string $name, float $tax): void {
$price = round($price * (1 + $tax), 2);
}, 0.2); // 20% tax
// Recursive version
$tree = [
'a' => [1, 2, 3],
'b' => [4, 5, 6],
'c' => 7,
];
array_walk_recursive($tree, function (int &$value): void {
$value *= 2;
});
// ['a' => [2, 4, 6], 'b' => [8, 10, 12], 'c' => 14]
Запомни:
array_map()возвращает НОВЫЙ массив.array_walk()модифицирует массив НА МЕСТЕ (in-place).array_walkполучает ключи в callback,array_map— нет.
Объединение массивов
array_merge vs оператор +
<?php
declare(strict_types=1);
// array_merge — reindexes numeric keys, later values overwrite string keys
$a = ['x' => 1, 'y' => 2, 0 => 'a'];
$b = ['x' => 3, 'z' => 4, 0 => 'b'];
$merged = array_merge($a, $b);
// ['x' => 3, 'y' => 2, 0 => 'a', 1 => 'b', 'z' => 4]
// Numeric keys REINDEXED, string 'x' overwritten by $b
// + operator — keeps FIRST occurrence, preserves all keys
$union = $a + $b;
// ['x' => 1, 'y' => 2, 0 => 'a', 'z' => 4]
// 'x' stays from $a, 0 stays from $a, 'z' added from $b
$c = [0 => 'zero-a', 1 => 'one-a'];
$d = [0 => 'zero-b', 1 => 'one-b', 2 => 'two-b'];
$union = $c + $d;
// [0 => 'zero-a', 1 => 'one-a', 2 => 'two-b']
// Existing keys NOT overwritten!
Ловушка экзамена:
array_merge(): числовые ключи переиндексируются, строковые ключи — последний побеждает+(union): ключи НЕ переиндексируются, ПЕРВЫЙ побеждает (существующие ключи не перезаписываются) Это ОЧЕНЬ частый вопрос сертификации!
Spread оператор vs array_merge
<?php
declare(strict_types=1);
$a = [1, 2, 3];
$b = [4, 5, 6];
// Both reindex numeric keys
$merged1 = array_merge($a, $b); // [1, 2, 3, 4, 5, 6]
$merged2 = [...$a, ...$b]; // [1, 2, 3, 4, 5, 6]
// With string keys (PHP 8.1+)
$defaults = ['color' => 'red', 'size' => 'M'];
$custom = ['size' => 'L', 'weight' => 100];
$config = [...$defaults, ...$custom];
// ['color' => 'red', 'size' => 'L', 'weight' => 100]
array_merge_recursive
<?php
declare(strict_types=1);
$a = ['color' => 'red', 'sizes' => ['S', 'M']];
$b = ['color' => 'blue', 'sizes' => ['L', 'XL']];
$result = array_merge_recursive($a, $b);
// [
// 'color' => ['red', 'blue'], — values merged into array!
// 'sizes' => ['S', 'M', 'L', 'XL'] — arrays merged
// ]
// Compare with array_merge:
$result = array_merge($a, $b);
// ['color' => 'blue', 'sizes' => ['L', 'XL']]
// Last value wins for string keys
Извлечение и проверка
<?php
declare(strict_types=1);
$user = ['name' => 'Alice', 'age' => 25, 'city' => 'Moscow'];
// Keys and values
$keys = array_keys($user); // ['name', 'age', 'city']
$values = array_values($user); // ['Alice', 25, 'Moscow']
// Combine arrays
$combined = array_combine(['a', 'b', 'c'], [1, 2, 3]);
// ['a' => 1, 'b' => 2, 'c' => 3]
// Flip keys and values
$flipped = array_flip(['a' => 1, 'b' => 2, 'c' => 3]);
// [1 => 'a', 2 => 'b', 3 => 'c']
// Unique values
$unique = array_unique([1, 2, 2, 3, 3, 3]);
// [0 => 1, 1 => 2, 3 => 3] — keys preserved!
// Count values
$counts = array_count_values(['a', 'b', 'a', 'c', 'b', 'a']);
// ['a' => 3, 'b' => 2, 'c' => 1]
// Slice
$slice = array_slice($values, 1, 2); // [25, 'Moscow']
$slice = array_slice($values, 1, 2, true); // [1 => 25, 2 => 'Moscow'] (preserve keys)
// Column from multidimensional array
$users = [
['name' => 'Alice', 'age' => 25],
['name' => 'Bob', 'age' => 30],
];
$names = array_column($users, 'name'); // ['Alice', 'Bob']
$indexed = array_column($users, null, 'name'); // Indexed by name
Разница массивов
<?php
declare(strict_types=1);
$a = [1, 2, 3, 4, 5];
$b = [3, 4, 5, 6, 7];
// array_diff — values in $a not in $b
$diff = array_diff($a, $b); // [0 => 1, 1 => 2]
// array_intersect — values in both
$inter = array_intersect($a, $b); // [2 => 3, 3 => 4, 4 => 5]
// Key-based versions
$x = ['a' => 1, 'b' => 2, 'c' => 3];
$y = ['a' => 1, 'b' => 5, 'd' => 3];
$diffKey = array_diff_key($x, $y); // ['c' => 3]
$diffAssoc = array_diff_assoc($x, $y); // ['b' => 2, 'c' => 3]
$interKey = array_intersect_key($x, $y); // ['a' => 1, 'b' => 2]