Объединение множеств в Python: оператор | и union
Гости субботы плюс гости воскресенья — но каждый посчитан один раз. Оператор | и метод union собирают два множества в одно без дубликатов.
Редакция Питоники
Одиночное множество — начало. Настоящая сила множеств раскрывается в операциях над парами: собрать всех гостей двух дней, все теги двух статей, все товары двух складов. Первая операция — объединение: всё, что есть хотя бы в одном из множеств, без повторов. У неё два лица: оператор | для лаконичного кода и метод union для работы с произвольными коллекциями. Разберём оба и главное правило подсчёта.
Задача: гости выходных
Клуб ведёт учёт посетителей по дням: в субботу приходили одни, в воскресенье — другие, часть гостей сходила оба дня. Вопрос: сколько разных людей побывало за выходные:
saturday = {'анна', 'борис', 'вера'}
sunday = {'вера', 'глеб', 'дарья'}
all_guests = saturday | sunday
print(sorted(all_guests))
print('за два дня:', len(all_guests))
['анна', 'борис', 'вера', 'глеб', 'дарья'] за два дня: 5
Пять гостей вместо шести записей: вера есть в обоих множествах, но в объединение попала один раз. Оператор | взял два множества и вернул третье — со всеми элементами каждого.
Сначала списком: дубликаты в придачу
Сравним со списочным решением той же задачи. Списки складываются знаком плюс — и вносят в сумму все дубликаты:
saturday = ['анна', 'борис', 'вера']
sunday = ['вера', 'глеб', 'дарья']
combined = saturday + sunday
print('в списке:', len(combined))
print(sorted(set(combined)))
в списке: 6 ['анна', 'борис', 'вера', 'глеб', 'дарья']
Шесть имён в списке, пять настоящих гостей: вера задвоилась, и снимать дубль пришлось отдельным вызовом set. Множества делают это при объединении — лишней строки не нужно.
Оператор | и метод union
Объединение пишут и методом union — результат тот же самый, это одна и та же операция в двух записях:
a = {1, 2, 3}
b = {3, 4}
print(sorted(a | b))
print(sorted(a.union(b)))
print(a | b == a.union(b))
[1, 2, 3, 4] [1, 2, 3, 4] True
Тройка общая — в объединении она одна. Оператор лаконичнее и уместен, когда оба операнда уже множества; метод читается словом и уместен, когда второй набор пришёл списком. Проверим подсчёт на числах, где видно каждое значение:
a = {1, 2, 3}
b = {3, 4}
u = a | b
print('у a:', len(a), '- у b:', len(b), '- в объединении:', len(u))
у a: 3 - у b: 2 - в объединении: 4
Три плюс два равно пять, но в объединении четыре: общая тройка вошла один раз. Общее правило подсчёта: длина объединения равна сумме длин минус число общих элементов. Оно же — определение уникальности: пересечение не удваивается.
union принимает список, | — нет
Метод union растёт из общего принципа множеств: всё перебираемое годится. Поэтому второй набор может быть и списком — union сам соберёт его в множество и вольёт:
a = {1, 2}
merged = a.union([3, 4])
print(sorted(merged))
try:
a | [3, 4]
except TypeError as e:
print('Ошибка:', e)
[1, 2, 3, 4] Ошибка: unsupported operand type(s) for |: 'set' and 'list'
Метод проглотил список и дал четыре элемента. Оператор на том же вызове упал: сообщение перечисляет типы обеих сторон — set и list — и отказывается их смешивать. Правило короткое: | для пары множеств, union для множества с чем угодно перебираемым.
Исходные не меняются: union возвращает новое
Объединение не трогает свои источники: | и union строят новое множество и оставляют оба набора нетронутыми. Проверим:
a = {1, 2}
b = {2, 3}
u = a | b
print(sorted(a), sorted(b))
print(sorted(u))
print(len(a), len(b))
[1, 2] [2, 3] [1, 2, 3] 2 2
Оба исходных множества остались при своих двух элементах, а объединение живёт в новой переменной. Это отличается от поведения update из урока про add и update: тот вливает элементы в существующее множество и ничего не возвращает. Выбор простой: нужно расширяющееся множество — update; нужно новое множество из двух — union.
А вот цикл с add для вливания пачки — наследие списочного мышления. Он работает, но вручную повторяет то, что операции множеств делают одним вызовом:
merged = set()
for guest in saturday:
merged.add(guest)
for guest in sunday:
merged.add(guest)
# всё это один вызов: merged = saturday | sunday
Объединение трёх множеств
Оператор можно выстроить в цепочку: a | b | c вычисляется слева направо — сначала объединение первых двух, потом к результату добавляется третье. Соберём стек технологий из трёх направлений:
mono = {'python', 'regex'}
web = {'python', 'flask'}
data = {'pandas', 'python'}
stack = mono | web | data
print(sorted(stack))
print(len(stack))
['flask', 'pandas', 'python', 'regex'] 4
Шесть записей в трёх множествах, четыре уникальных: питон повторялся во всех трёх и попал в стек один раз. Метод тоже цепляется: mono.union(web, data) — union, в отличие от оператора, принимает несколько аргументов сразу.
Шпаргалка объединения
Две записи одной операции и близнец update — всё объединение умещается в таблицу:
| Выражение | Что делает | Особенность |
|---|---|---|
| a | b | Новое множество из всех элементов | Обе стороны — множества |
| a.union(b) | То же объединение, методом | Принимает список и перебираемое |
| a.union(b, c) | Объединение трёх и больше | Аргументы через запятую |
| a.update(b) | Вливает b в a на месте | Возвращает None, меняет a |
| a + b | Такой операции нет | Для списков плюс несёт дубликаты |
Объединение собирает всех участников сцены. Обратный вопрос — кто присутствует в обоих множествах сразу — отвечает пересечение: оператор & и метод intersection из следующего урока. А быструю проверку принадлежности, которая лежит в основе всех этих операций, мы разобрали в уроке про in.
Сначала предскажи ответ в голове — это главный навык программиста.
a = {1, 2}
b = {2, 3}
print(sorted(a | b))
print(len(a), len(b), len(a | b))
x = {'a'}
y = x.union(['b'])
print(sorted(x))
print(sorted(y))
print(len(x) == len(y))
mono = {1, 2}
web = {2, 3}
data = {3, 4}
all_x = mono | web | data
print(sorted(all_x))
print(len(all_x))
1. Что вернёт {1, 2} | {2, 3}?
2. Чем a.union(b) отличается от a.update(b)?
3. Что произойдёт с общими элементами двух множеств при объединении?
4. Что вернёт a.union([3, 4]), если a — множество {1, 2}?
5. Что произойдёт при a | [3, 4]?
6. Как объединить три множества a, b и c?
Даны гости двух дней: first_day = {'vk', 'tg'} и second_day = {'tg', 'ok'}. Соберите всех гостей через | в переменную weekend и напечатайте отсортированный список и количество гостей.
Как объединить два множества в Python?
Оператором | или методом union: saturday | sunday вернёт новое множество со всеми элементами обоих, и общие элементы войдут один раз. Исходные множества не меняются. Для цепочки — a | b | c.
Урок 7: пересечение множествЧем оператор | отличается от union?
Только требованиями к аргументам. | работает с парой множеств и падает на списке; union принимает любой перебираемый — список, кортеж, строку — и даже несколько аргументов сразу: a.union(b, c). Результат обеих записей одинаков.
Почему объединение не создаёт дубликаты?
Потому что результат — множество: уникальность встроена в структуру. Общие элементы двух наборов кладутся в новую хеш-таблицу, где каждое значение живёт один раз. Поэтому длина объединения равна сумме длин минус число общих элементов.
Как объединить список с множеством?
Методом union: a.union([3, 4]) соберёт множество из a и списка. Оператор | так не умеет — он требует множество с обеих сторон и падает с TypeError на списке. Альтернатива — a | set([3, 4]).
Чем union отличается от update?
Результатом. union возвращает новое множество и оставляет источники нетронутыми; update вливает второй набор в первое множество на месте и возвращает None. Нужен расширяющийся список гостей — update; нужно новое множество из двух — union.
Урок 3: add и updateПонравился урок? Сошлитесь на него
«Общее правило подсчёта: длина объединения равна сумме длин минус число общих элементов.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Множества · Урок 7
Пересечение множеств Python: оператор & и intersection
Общие элементы двух множеств одним знаком: & находит тех, кто есть в обоих. Пустое пересечение, isdisjoint и пересечение трёх наборов.
Множества · Урок 3
add и update в Python: добавление элементов в set
Множество собрано — теперь пополняем: add кладёт один элемент, update принимает списки, множества и даже строки. Дубликаты исчезают тихо, без ошибок.
Множества · Урок 5
in в Python: мгновенная проверка принадлежности множеству
Один оператор, два механизма: in у множества отвечает мгновенно, у списка — перебором. Почему на миллионе элементов разница становится днями и секундами.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
Словари · Урок 14
Объединение словарей: update и оператор |
Два словаря в один: update переписывает на месте, оператор | собирает новый словарь, слои настроек ставятся по приоритету, а при конфликте ключей побеждает правый.
объединение словарей pythonоператор | словари python
NumPy · Урок 7
Многомерные массивы и оси: reshape, axis и работа с матрицами
Форма массива — это взгляд на данные: reshape и магия -1, оси axis на пальцах, транспонирование T, матричное умножение @ и склейка vstack/hstack.
как объединить два массива numpy concatenatenumpy матрицы операции
Множества · Урок 8
Разность и симметричная разность множеств в Python
Разность отвечает на вопрос «что есть у первого и чего нет у второго», симметричная — «что есть ровно у одного из двух». Операторы - и ^, методы difference и symmetric_difference и почему порядок множеств важен.
python разность множествразность множеств python