Перейти к содержанию

412 уроков, 25 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 7 из 20 Начальный 15 мин 100 XP

Пересечение множеств Python: оператор & и intersection

Общие элементы двух множеств одним знаком: & находит тех, кто есть в обоих. Пустое пересечение, isdisjoint и пересечение трёх наборов.

Редакция Питоники

Объединение прошлого урока собирало всех. Пересечение работает наоборот: находит только то, что присутствует в обоих множествах сразу. Кто пришёл оба дня, какие теги у двух статей общие, какие товары есть на обоих складах — все эти вопросы об общих значениях решаются одним знаком &. Операции парные: у оператора есть метод intersection, у пересечения — свойство быть пустым, и отдельная быстрая проверка isdisjoint.

Задача: гости обоих дней

Вернёмся к клубу: в субботу и воскресенье списки гостей частично совпадают. Вопрос дня — кто ходил оба раза, самые преданные гости:

кто пришёл оба дня
saturday = {'анна', 'борис', 'вера'}
sunday = {'вера', 'глеб', 'анна'}
both_days = saturday & sunday
print(sorted(both_days))
print('пришли оба дня:', len(both_days))
Вывод
['анна', 'вера']
пришли оба дня: 2

Анна и вера — в обоих списках, остальные гости ходили один раз и в пересечение не попали. Оператор & вернул новое множество из общих элементов; два исходных списка остались целы.

Оператор & и метод intersection

Как и объединение, пересечение пишется двумя записями. Метод intersection делает ровно то же, что &, — это одна операция в двух одеждах:

& и intersection равны
a = {1, 2, 3}
b = {2, 3, 4}
print(sorted(a & b))
print(sorted(a.intersection(b)))
print(a & b == a.intersection(b))
Вывод
[2, 3]
[2, 3]
True

Двойка и тройка — общие: они и есть пересечение. Полезное следствие: пересечение множества с самим собой возвращает копию — все элементы совпадают с собой:

пересечение с самим собой — копия
a = {1, 2, 3}
same = a & a
print(sorted(same))
print(a == same)
Вывод
[1, 2, 3]
True

same — новое множество с тем же содержанием: проверка равенства подтверждает. В остальном пересечение ведёт себя как любая операция пары: результат строится заново, источники не трогаются.

intersection принимает список, & — нет

Метод унаследовал правило множеств: перебираемое годится. Поэтому искать общие элементы можно между множеством и списком — например, между тегами статьи и поисковым запросом:

intersection со списком
tags_post = {'python', 'web', 'sql'}
search = ['python', 'sql', 'html']
common = tags_post.intersection(search)
print(sorted(common))
Вывод
['python', 'sql']

Два тега статьи совпали с запросом — intersection сам разобрал список и нашёл общие. Оператор & на том же вызове упадёт: он требует множество с обеих сторон.

& со списком падает
a = {1, 2}
a & ['python']
Вывод
Traceback (most recent call last):
  File "app.py", line 2, in <module>
    a & ['python']
    ~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for &: 'set' and 'list'
Программа падает на пересечении со списком: оператор требует множество с обеих сторон. Путь к файлу в traceback будет вашим (показан условный app.py).

Общих элементов нет — пустое множество

Что если общих элементов не существует? Пересечение честно вернёт пустое множество — не ошибку и не None. Проверим на чётных и нечётных числах:

пустое пересечение
even = {2, 4, 6}
odd = {1, 3, 5}
common = even & odd
print(len(common))
print(bool(common))
print(even.isdisjoint(odd))
Вывод
0
False
True

Три ответа о пустоте: длина ноль, булево значение False — пустое множество считается ложью, а метод isdisjoint вернул True: множества действительно не пересекаются. isdisjoint — самый честный вопрос на этот случай: он отвечает сразу True или False, не строя промежуточного множества.

Исходные не меняются; пересечение трёх

Пересечение возвращает новое множество, и исходные наборы остаются полными — это удобно для цепочек: a & b & c вычисляется слева направо и отвечает, что есть во всех трёх сразу:

пересечение трёх множеств
a = {1, 2, 3}
b = {2, 3, 4}
c = {3, 5}
all_three = a & b & c
print(sorted(all_three))
print(len(a), len(b))
Вывод
[3]
3 3

Только тройка живёт во всех трёх множествах. Оба исходных набора остались по три элемента: пересечение никого не вычеркнуло, оно собрало новое множество из общих. Метод умеет то же одним вызовом: a.intersection(b, c) принимает несколько аргументов.

Практика: общие теги двух статей

Живой пример на строках: два поста блога, вопрос — какие темы у них общие. Пересечение даёт ответ одной строкой:

общие теги двух статей
post1 = {'python', 'множества', 'уроки'}
post2 = {'python', 'списки', 'уроки'}
common = post1 & post2
print('общих тегов:', len(common))
print(sorted(common))
Вывод
общих тегов: 2
['python', 'уроки']

Python и уроки — общие темы, множества и списки — индивидуальные. По той же схеме ищут общих друзей двух профилей, совпадения товаров в корзинах и пересечения аудиторий — везде, где нужно найти общее в двух наборах.

Шпаргалка пересечения

Обе записи операции и вспомогательные проверки — в одной таблице:

ВыражениеЧто делаетОсобенность
a & bНовое множество из общих элементовОбе стороны — множества
a.intersection(b)То же пересечение, методомПринимает список и перебираемое
a.intersection(b, c)Общее для трёх и большеАргументы через запятую
a.isdisjoint(b)True, если общих нетБез построения нового множества
len(a & b) == 0Проверка пустоты вручнуюРаботает, но isdisjoint читается лучше

Пересечение нашло общее. Следующая операция пары — разность: что есть у одного множества и отсутствует у другого, со знаком минус и порядком, который здесь впервые станет важным. Ей посвящён урок 8, а задачи на совместные операции множеств ждут в уроке про практику.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

a = {1, 2, 3}
b = {3, 4}
print(sorted(a & b))
print(len(a & b))
x = {'a', 'b'}
y = ['b', 'c']
common = x.intersection(y)
print(sorted(common))
print(len(x), len(y))
even = {2, 4}
odd = {1, 3}
common = even & odd
print(len(common))
print(even.isdisjoint(odd))
Проверь себя
0 / 6

1. Что вернёт {1, 2, 3} & {2, 3, 4}?

2. Что вернёт a.intersection([2, 3]), если a — множество {2, 5}?

3. Что произойдёт при a & [2, 3]?

4. Общих элементов у двух множеств нет. Что вернёт a & b?

5. Что означает результат a.isdisjoint(b) == True?

6. Меняет ли пересечение исходные множества?

Карточки терминов
Запомнено: 0 / 7
Практика

Даны теги двух статей: post1 = {'python', 'set', 'основы'} и post2 = {'python', 'list', 'основы'}. Найдите общие теги через & и напечатайте две строки: общих N и отсортированный список.

practice.py
Вопросы и ответы по уроку

Как найти общие элементы двух множеств в Python?

Оператором & или методом intersection: saturday & sunday вернёт новое множество из элементов, которые есть в обоих наборах. Исходные множества не меняются. Для цепочки из трёх и больше — a & b & c или a.intersection(b, c).

Урок 6: объединение множеств

Чем оператор & отличается от intersection?

Только требованиями к аргументам. & требует множество с обеих сторон и падает с TypeError на списке; intersection принимает любой перебираемый — список, кортеж — и несколько аргументов сразу. Результат обеих записей одинаков.

Что вернёт пересечение, если общих элементов нет?

Пустое множество: len(a & b) равен 0, bool от него — False. Это не ошибка. Для прямой проверки без построения промежуточного множества есть метод isdisjoint: True означает, что множества не пересекаются.

Как проверить, что множества не пересекаются?

Методом isdisjoint: a.isdisjoint(b) возвращает True, если общих элементов нет, и False, если есть хотя бы один. Вторым аргументом может быть и список. Запись len(a & b) == 0 работает тоже, но строит лишнее множество.

Как найти пересечение множества и списка?

Методом intersection: tags.intersection(['python', 'sql']) найдёт общие элементы множества и списка. Оператор & на списке падает — он требует множество с обеих сторон; список можно обернуть в set и использовать &.

Понравился урок? Сошлитесь на него

«isdisjoint — самый честный вопрос на этот случай: он отвечает сразу True или False, не строя промежуточного множества.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.

NumPy · Урок 4

Операции с массивами: векторизация и почему NumPy быстрее списков в 100 раз

Умножаем миллион цен одной строкой и замеряем время через time.perf_counter: почему векторизация NumPy обгоняет цикл for в десятки раз. Ufunc, np.dot, булевы сравнения и правило «никаких for там, где есть операция».

операции с массивами numpyпоэлементные операции numpy

Функции · Урок 3

Return в Python: функция возвращает результат

print показывает значение человеку, return отдаёт программе. Учимся возвращать результат, класть его в переменную и использовать в выражениях — и не путать return с print.

оператор return python

Множества · Урок 17

Множества и словари Python: hash и общие механизмы

Множество и словарь построены на одном механизме: hash назначает каждому элементу полку, и проверка in становится мгновенной. Ключи словаря — готовое множество, над которым работают & и |.

python множества и словариpython dict keys intersection