🐘 PHP

PHP 8.2 中的集合(Set):详细指南

Множества (Set) в PHP

Что такое множество и зачем оно нужно?

Представь, что у тебя есть коробка, в которую можно класть только уникальные предметы. Если ты попытаешься положить туда второй такой же предмет, коробка его просто не примет. В PHP такая «коробка» называется множеством (Set).

Множества помогают решать задачи, где нужно:

  • Убрать повторяющиеся элементы (например, оставить только уникальные ингредиенты для пиццы).
  • Проверить, есть ли элемент в наборе (например, есть ли товар в списке обязательных).
  • Объединить два списка без дубликатов.

В PHP нет отдельного класса «Set», но мы можем использовать массивы с ключами или встроенный класс Ds\Set из расширения Data Structures. Для начинающих проще всего работать с обычными массивами, используя функцию array_unique().

Основной синтаксис

Самый простой способ создать множество — взять массив и удалить из него дубликаты:

// Создаём массив с повторениями
$ingredients = ['сыр', 'помидор', 'сыр', 'грибы', 'помидор'];

// Превращаем в множество (удаляем дубликаты)
$unique_ingredients = array_unique($ingredients);

print_r($unique_ingredients);
/* Вывод:
Array
(
    [0] => сыр
    [2] => грибы
    [3] => помидор
)
*/

Обрати внимание: индексы сохраняются, но значения стали уникальными.

Чтобы проверить, есть ли элемент в множестве, используем in_array():

$fruits = ['яблоко', 'банан', 'апельсин'];

if (in_array('банан', $fruits)) {
    echo "Банан есть в списке!";
} else {
    echo "Бабана нет :(";
}
// Вывод: Банан есть в списке!

Для объединения двух множеств без дубликатов используем array_merge() и array_unique() вместе:

$list1 = ['молоко', 'хлеб', 'яйца'];
$list2 = ['хлеб', 'сок', 'печенье'];

$merged = array_unique(array_merge($list1, $list2));
print_r($merged);
// Array ( [0] => молоко [1] => хлеб [2] => яйца [3] => сок [4] => печенье )

Разбор типичных задач

Задача 1: Ингредиенты пиццы

Пользователь вводит ингредиенты через запятую. Нужно вывести только уникальные.

echo "Введите ингредиенты через запятую: ";
$input = trim(fgets(STDIN));
$items = explode(',', $input);
$items = array_map('trim', $items); // убираем лишние пробелы

$unique = array_unique($items);
echo "Уникальные ингредиенты:\n";
foreach ($unique as $item) {
    echo "- $item\n";
}

/* Пример работы:
Введите ингредиенты через запятую: сыр, помидор, сыр, грибы, помидор
Уникальные ингредиенты:
- сыр
- помидор
- грибы
*/

Задача 2: Объединение списков покупок

У вас есть свой список, и друзья добавили свои пункты. Нужно получить итоговый список без повторов.

$my_list = ['кола', 'чипсы', 'пицца'];
echo "Мой список: " . implode(', ', $my_list) . "\n";

echo "Введите добавки друзей через запятую: ";
$friends_input = trim(fgets(STDIN));
$friends_items = explode(',', $friends_input);
$friends_items = array_map('trim', $friends_items);

$final_list = array_unique(array_merge($my_list, $friends_items));
echo "Итоговый список покупок:\n";
foreach ($final_list as $item) {
    echo "- $item\n";
}

/* Пример:
Мой список: кола, чипсы, пицца
Введите добавки друзей через запятую: сок, чипсы, печенье
Итоговый список покупок:
- кола
- чипсы
- пицца
- сок
- печенье
*/

Задача 3: Проверка наличия товара

У вас есть список обязательных товаров. Нужно проверить, все ли они есть в наличии.

$required = ['хлеб', 'молоко', 'яйца', 'масло'];
echo "Обязательные товары: " . implode(', ', $required) . "\n";

echo "Введите товары в наличии через запятую: ";
$stock_input = trim(fgets(STDIN));
$stock = explode(',', $stock_input);
$stock = array_map('trim', $stock);

$missing = [];
foreach ($required as $item) {
    if (!in_array($item, $stock)) {
        $missing[] = $item;
    }
}

if (empty($missing)) {
    echo "Все обязательные товары есть в наличии!";
} else {
    echo "Не хватает: " . implode(', ', $missing);
}

/* Пример:
Обязательные товары: хлеб, молоко, яйца, масло
Введите товары в наличии через запятую: хлеб, яйца, сок
Не хватает: молоко, масло
*/

Частые ошибки новичков

  • Забывают про пробелы. Если пользователь вводит «сыр, помидор», то после explode получится ['сыр', ' помидор'] — это разные строки. Всегда используйте array_map('trim', ...).
  • Путают in_array и array_search. in_array() просто проверяет, есть ли элемент (возвращает true/false). array_search() ищет и возвращает ключ.
  • Думают, что array_unique сохраняет порядок. Он сохраняет порядок первых вхождений. Это нормально для большинства задач.
  • Используют array_unique на многомерных массивах. Он работает только с одномерными массивами строк или чисел.

Итоговый пример: Записная книжка контактов

Давай решим задачу «Записная книжка контактов» с помощью множеств. Мы будем хранить имена (уникальные) и номера телефонов.

echo "=== ЗАПИСНАЯ КНИЖКА КОНТАКТОВ ===\n";
echo "Введите имена через запятую: ";
$names_input = trim(fgets(STDIN));
$names = explode(',', $names_input);
$names = array_map('trim', $names);

echo "Введите номера телефонов через запятую (в том же порядке): ";
$phones_input = trim(fgets(STDIN));
$phones = explode(',', $phones_input);
$phones = array_map('trim', $phones);

// Создаём множество уникальных имён
$unique_names = array_unique($names);

$contacts = [];
foreach ($unique_names as $index => $name) {
    // Берём телефон по тому же индексу (если есть)
    $phone = $phones[$index] ?? 'неизвестен';
    $contacts[$name] = $phone;
}

echo "\nВаши контакты (уникальные имена):\n";
foreach ($contacts as $name => $phone) {
    echo "$name: $phone\n";
}

/* Пример работы:
=== ЗАПИСНАЯ КНИЖКА КОНТАКТОВ ===
Введите имена через запятую: Анна, Борис, Анна, Виктор
Введите номера телефонов через запятую (в том же порядке): 111, 222, 333, 444

Ваши контакты (уникальные имена):
Анна: 111
Борис: 222
Виктор: 444
*/

Обрати внимание: Анна встречалась дважды, но в книжке осталась только одна запись с первым номером. Так множества помогают избегать дубликатов!