К содержанию

Модуль 4 · Урок 4.5

Множества и выбор структуры данных

Только различные значения, быстрые проверки принадлежности и операции над множествами.

5 задач

Сколько разных слов в тексте? Кто есть в обоих списках участников? На такие вопросы неважны порядок и повторы — важно только, какие значения встречаются. Множество хранит только различные значения и быстро отвечает «есть ли элемент». Это как ключи словаря без значений, с теми же требованиями к элементам.

Возьмём список [3, 1, 3, 2, 1] и два списка участников, в которых найдём общих людей.

Множество

Множество оставляет только различные значения. Множество (set) хранит каждое значение один раз и быстро проверяет, есть ли оно. Элементами, как и ключами словаря, могут быть числа, строки и кортежи из них.

values = [3, 1, 3, 2, 1]unique = set(values)print(len(unique))print(2 in unique)
3 True

Из пяти чисел различных три: 1, 2 и 3. Множество не сохраняет смыслового порядка и не поддерживает обращение по индексу. То, что в отдельном запуске вывод выглядит упорядоченным, не даёт права на это рассчитывать. Как получить упорядоченный результат, покажет урок о сортировке.

Пустое множество — set(). Запись {} создаёт пустой словарь. Непустое множество можно записать {1, 2, 3}.

print(type({}), type(set()), type({1, 2}))
<class 'dict'> <class 'set'> <class 'set'>

Операции над множествами

Множества объединяют, пересекают и вычитают.

a = {1, 2, 3}b = {3, 4}print(a | b)print(a & b)print(a - b)print(a ^ b)print({1, 2} <= a)
{1, 2, 3, 4} {3} {1, 2} {1, 2, 4} True

a | b — объединение: элементы из любого множества. a & b — пересечение: элементы одновременно в обоих. a - b — разность: элементы a, отсутствующие в b. a ^ b — элементы ровно одного из двух множеств. <= проверяет, что первое множество — подмножество второго.

Одни и те же множества: 1 и 2 только в a, 3 в обоих, 4 только в b. Цветом выделен результат каждой операции.

add(x) добавляет элемент, update(items) — все элементы источника, discard(x) удаляет, если он присутствует. remove(x) тоже удаляет, но отсутствие вызывает ошибку:

s = {1, 2}s.add(2)s.update([3, 4])s.discard(9)print(s)s.remove(9)
{1, 2, 3, 4} KeyError: 9

Повторное add(2) ничего не изменило: элемент уже есть.

Тонкости:& для чисел и frozenset

Один и тот же знак означает разное для разных типов: для множеств & — пересечение, для целых чисел — операция над битами (урок о записи чисел), а логическое «и» — это and. frozenset — неизменяемое множество; его можно сделать ключом словаря.

Выбор структуры

Структуру данных выбирают по тому, какие действия нужны. Список — когда важны порядок и повторы, а элементы меняются. Кортеж — короткая неизменяемая запись. Словарь — когда значение ищут по ключу. Множество — когда важны только различные значения и вопрос «есть ли такое». Сводка всех пяти — в конце модуля, в уроке о включениях.

Выбор зависит от нужных действий, а не только от вида исходных данных. Чтобы посчитать количество разных слов, достаточно множества. Чтобы посчитать частоту каждого, нужен словарь.

Общие элементы

Общие элементы двух списков — пересечение их множеств. Есть два списка участников; найдём людей, присутствующих в обоих. Пока порядок результата не важен.

first = ["Анна", "Илья", "Анна"]second = ["Илья", "Марк"]common = set(first) & set(second)print(common)
{'Илья'}

Повторяющаяся Анна в первом списке не создаёт вторую копию человека во множестве. Если повторы означают отдельные события и должны учитываться, множество теряет нужную информацию.

Итог

Множество отвечает на вопросы «есть ли» и «сколько разных», а структуру данных выбирают по нужным действиям. Вот что понадобится дальше.

  • set(items)set(items) оставляет различные значения; порядка и индексов нет.
  • Пустое множество{} — пустой словарь, пустое множество — set().
  • Операции|, &, -, ^ — объединение, пересечение, разность, «ровно в одном».
  • Изменениеadd, update, discard меняют множество; remove отсутствующего даёт KeyError.
  • ВыборКоличество разных — множество, частота каждого — словарь.

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1

Что напечатает print(len(set([3, 1, 3, 2, 1])))?

ОтветСкрыть ответ
Ответ

3: различные значения — 1, 2 и 3.

Вопрос 2

Есть два списка участников. Найди людей, присутствующих в обоих, для ["Оля", "Петя", "Вера"] и ["Вера", "Оля", "Оля"].

ОтветСкрыть ответ
Ответ

{'Оля', 'Вера'} — порядок вывода может быть любым.

Вопрос 3

Для a = {1, 2, 3, 4} и b = {3, 4, 5} найди a | b, a & b, a - b и a ^ b.

ОтветСкрыть ответ
Ответ

{1, 2, 3, 4, 5}, {3, 4}, {1, 2} и {1, 2, 5}.

Вопрос 4

Какой тип у {}? Как создать пустое множество?

ОтветСкрыть ответ
Ответ

dict; пустое множество — set().

Вопрос 5

Начни с s = {1, 2} и выполни s.add(2), s.update([3, 4]), s.discard(9). Чему равно s? Что сделает s.remove(9)?

ОтветСкрыть ответ
Ответ

{1, 2, 3, 4}; remove(9) — KeyError.

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Что напечатает программа?

print(len(set("BANANA")))

Введите число.

Что выбрать: список, множество или словарь

Что выбрать — список, множество или словарь — для задач: 1) число разных слов текста; 2) частота каждого слова; 3) все слова по порядку с повторами?

Запишите три слова через пробел в порядке задач: «список», «множество» или «словарь».

Что напечатает программа?

print(len(set("2026101")))

Введите число.

Напиши программу: кратные 3 или 5 до 50

Напиши программу: собери множество чисел от 1 до 50, кратных 3, и множество кратных 5, объедини их и напечатай размер объединения. Запусти её и запиши ответ.

Введите число.

Буквы «программы», которых нет в «информатике»

Какие буквы слова «программа» не встречаются в слове «информатика»? Подсказка в коде: разность множеств.

Запишите буквы через пробел в алфавитном порядке.