Как найти пересечение двух множеств python

Множеством в языке программирования Python называется неупорядоченная совокупность уникальных значений. В качестве элементов этого набора данных могут выступать любые неизменяемые объекты, такие как числа, символы, строки. В отличие от массивов и списков, порядок следования значений не учитывается при обработке его содержимого. Над одним, а также несколькими множествами можно выполнять ряд операций, благодаря функциям стандартной библиотеки языка программирования Python.

Создание

Перед тем как начать работу с множеством, необходимо для начала его создать. Сделать это можно, просто присвоив переменной последовательность значений, выделив их фигурными скобками. Следующий пример показывает код, в котором создается множество целых чисел под названием a, после функция print выводит на экран его содержимое.

a = {1, 2, 0, 1, 3, 2}
print(a)

{0, 1, 2, 3}

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

a = set('data')
print(a)

{'d', 'a', 't'}

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

Использование

Обычно используется для следующих операций:

  • Проверка, есть ли данное значение в множестве. Для этого используется in.
    a = {0, 1, 2, 3}
    print(2 in a)
    
    True
  • Наоборот, проверка отсутствия. Используется not in.
    a = {0, 1, 2, 3}
    print(2 not in a)
    
    False
  • Перебор всех элементов.
    for a in {0, 1, 2}:
        print(a)
    
    0
    1
    2

Генератор

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

Следующий код демонстрирует генерацию множества a с циклом for для нескольких чисел.

a = {i for i in [1, 2, 0, 1, 3, 2]}
print(a)

{0, 1, 2, 3}

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

Изменение множеств

Для управления содержимым множеств в языке Python присутствуют специальные методы, дающие возможность добавлять и удалять отдельные элементы.

Получение размера

Узнать точное количество элементов, входящих в состав множества, поможет метод len, принимающий в качестве аргумента набор данных. Функция print выводит результат.

a = {0, 1, 2, 3}
print(len(a))

4

Добавление элемента

Чтобы внести новые значения, потребуется вызывать метод add. Аргументом в данном случае будет добавляемый элемент последовательности. В примере кода на Python добавим в множество элемент со значением 4.

a = {0, 1, 2, 3}
a.add(4)
print(a)

{0, 1, 2, 3, 4}

Удаление элемента

Для удаления элементов из множества используются следующие функции в Python (кроме очистки, которая будет рассмотрена ниже):

  • remove — удаление элемента с генерацией исключения в случае, если такого элемента нет;
  • discard — удаление элемента без генерации исключения, если элемент отсутствует;
  • pop — удаление первого элемента, генерируется исключение при попытке удаления из пустого множества.

Избавиться от лишних значений в наборе данных с помощью remove. В качестве входного параметра здесь выступает элемент, который нужно удалить (в примере удалим число со значением 3).

a = {0, 1, 2, 3}
a.remove(3)
print(a)

{0, 1, 2}

По поводу функции pop хотелось бы отметить, что так как множества не упорядочены, то удалится случайный элемент, который будет находиться в памяти первым. Но если они в памяти хранятся в отсортированном виде, что не факт, то скорее всего будет удален элемент с наименьшим значением. Но на это не стоит рассчитывать.

Полная очистка

Иногда необходимо полностью убрать все элементы. Чтобы не удалять каждый элемент отдельно, используется метод clear, не принимающий аргументов. Если вывести содержимое после этой операции, на экране появится только его название.

a = {0, 1, 2, 3}
a.clear()
print(a)

set()

В результате получили пустое множество.

Сортировка

Порядок следования элементов не учитывается. Поэтому нет смысла говорить о сортировке множеств в Python 3.

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

В начале рассмотрим, что будет с элементами разных типов данных в одном множестве. Такие элементы не должны сортироваться. Если мы будем выводить элементы с помощью команды print, то они выводятся примерно следующим образом:

a = {0, 1, 12, 'b', 'ab', 3, 2, 'a'}
print(a)

{0, 1, 'b', 3, 2, 12, 'ab', 'a'}

Как видим, у нас вывелись не отсортированные значения, если повторить запуск, то порядок будет меняться. Но это только в том случае, если перемешаны элементы разного типа.

Посмотрим, что будет, если попытаемся вывести только числа:

a = {0, 1, 12, 3, 2}
print(a)

{0, 1, 2, 3, 12}

Все элементы выведены упорядоченно. Теперь посмотрим что будет если преобразовать в список:

a = {0, 1, 12, 3, 2}
b = list(a)
print(b)

[0, 1, 2, 3, 12]

Аналогично, в список значения записались отсортированными по возрастанию.

Получается, что элементы хранятся в памяти в упорядоченном виде, если они одного типа. Но лучше не стоит на это расчитывать, алгоритмы Python могут поменяться.

Если вам нужно получить отсортированный список из множества, лучше воспользоваться для верности функцией sort. Элементы будут точно отсортированы. Ваш код будет понятен для других.

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

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

Рассмотрим операции с множествами доступные в Python 3.

Объединение

Чтобы объединить все элементы двух разных множеств, стоит воспользоваться методом union на одном из объектов. Следующий пример демонстрирует работу данной функции, где создается последовательность чисел под именем c.

a = {0, 1, 2, 3}
b = {4, 3, 2, 1}
c = a.union(b)
print(c)

{0, 1, 2, 3, 4}

Добавление

Чтобы добавить все элементы из одного множества к другому, необходимо вызывать метод update на первом объекте. Таким образом можно перенести уникальные данные из одного набора чисел в другой, как это показано в следующем примере.

a = {0, 1, 2, 3}
b = {4, 3, 2, 1}
a.update(b)
print(a)

{0, 1, 2, 3, 4}

Пересечение

Чтобы найти общие элементы для двух разных множеств, следует применить функцию intersection, принимающую в качестве аргумента один из наборов данных. Код, приведенный ниже, создает новую последовательность чисел из пересечения двух множеств в Python 3.

a = {0, 1, 2, 3}
b = {4, 3, 2, 1}
c = a.intersection(b)
print(c)

{1, 2, 3}

Разность

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

a = {0, 1, 2, 3}
b = {4, 3, 2, 1}
c = a.difference(b)
print(c)

{0}

Отношения между множествами

Для определения подмножеств и надмножеств существуют специальные функции, возвращающие True или False в зависимости от результата выполнения.

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

Чтобы выяснить, является ли множество a подмножествомb, стоит попробовать вывести на экран результат выполнения метода issubset, как в следующем примере. Так как не все элементы набора чисел a присутствуют в b, функция вернет False.

a = {0, 1, 2, 3, 4}
b = {3, 2, 1}
print(a.issubset(b))

False

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

Чтобы узнать, является ли множество a надмножеством b, необходимо вызвать метод issuperset и вывести результат его работы на экран. Поскольку все элементы набора чисел b присутствуют в a, функция возвращает True.

a = {0, 1, 2, 3, 4}
b = {3, 2, 1}
print(a.issuperset(b))

True

Тип frozenset

Множество, содержимое которого не поддается изменению имеет тип frozenset. Значения из этого набора нельзя удалить, как и добавить новые. В следующем примере демонстрируется создание при помощи стандартной функции.

a = frozenset({"hello", "world"})
print(a)

frozenset({'hello', 'world'})

Поскольку содержимое frozenset должно всегда оставаться статичным, перечень функций, с которыми такое множество может взаимодействовать, имеет ограничения.

Преобразование множеств

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

Строка

Для преобразования множества в строку используется конкатенация текстовых значений, которую обеспечивает функция join. В этом случае ее аргументом является набор данных в виде нескольких строк. Запятая в кавычках выступает в качестве символа, разделяющего значения. Метод type возвращает тип данных объекта в конце приведенного кода.

a = {'set', 'str', 'dict', 'list'}
b = ','.join(a)
print(b)
print(type(b))

set,dict,list,str
<class 'str'>

Словарь

Чтобы получить из множества словарь, следует передать функции dict набор из нескольких пар значений, в каждом из которых будет находиться ключ. Метод print демонстрирует на экране содержимое полученного объекта, а type отображает его тип.

a = {('a', 2), ('b', 4)}
b = dict(a)
print(b)
print(type(b))

{'b': 4, 'a': 2}
<class 'dict'>

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

  1. ключ будущего словаря;
  2. значение, соответствующее ключу.

Список

По аналогии с предыдущими преобразованиями можно получить список неких объектов. На этот раз используется метод list, получающий в качестве аргумента множество a. На выходе функции print отображаются уникальные значения для изначального набора чисел.

a = {1, 2, 0, 1, 3, 2}
b = list(a)
print(b)
print(type(b))

[0, 1, 2, 3]
<class 'list'>

Резюме

Следующая таблица отображает краткую сводку по всем пройденным функциям, включая их названия и назначение.

Название Назначение
len Получение размера
add Добавление элемента
remove Удаление элемента
clear Очистка
union Объединение
update Добавление всех элементов одного множества в другое
intersection Нахождение множества, элементы которого находятся на пересечении двух множеств
difference Нахождение множества, элементы которого входят в первое, но не входят во второе множество
issubset Проверка, является ли множество подмножеством
issuperset Проверка, является ли множество надмножеством

Заключение

Таким образом, были рассмотрены базовые возможности множеств стандартной библиотеки языка программирования Python. Использование этой совокупности уникальных значений, позволяет не только манипулировать различными видами данных, производя объединение, пересечение и вычитание определенных элементов. Благодаря стандартным функциям по работе с множествами, программист получает возможность конвертировать их в другие типы данных, обладающие упорядоченностью, такие как строка, список и словарь.

Время на прочтение
11 мин

Количество просмотров 93K

Python и теория множеств

В Python есть очень полезный тип данных для работы с множествами – это set. Об этом типе данных, примерах использования, и небольшой выдержке из теории множеств пойдёт речь далее.

Следует сразу сделать оговорку, что эта статья ни в коем случае не претендует на какую-либо математическую строгость и полноту, скорее это попытка доступно продемонстрировать примеры использования множеств в языке программирования Python.

  • Множество
  • Множества в Python
    • Хешируемые объекты
  • Свойства множеств
    • Принадлежность множеству
    • Мощность множества
    • Перебор элементов множества
  • Отношения между множествами
    • Равные множества
    • Непересекающиеся множества
    • Подмножество и надмножество
  • Операции над множествами
    • Объединение множеств
    • Добавление элементов в множество
    • Пересечение множеств
    • Разность множеств
    • Удаление элементов из множества
    • Симметрическая разность множеств
  • Заключение
  • Полезные ссылки

Множество

Множество – это математический объект, являющийся набором, совокупностью, собранием каких-либо объектов, которые называются элементами этого множества. Или другими словами:

Множество – это не более чем неупорядоченная коллекция уникальных элементов.

Что значит неупорядоченная? Это значит, что два множества эквивалентны, если содержат одинаковые элементы.

Элементы множества должны быть уникальными, множество не может содержать одинаковых элементов. Добавление элементов, которые уже есть в множестве, не изменяет это множество.

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

Множества в Python

Множество в Python можно создать несколькими способами. Самый простой – это задать множество перечислением его элементов в фигурных скобках:

fruits = {"banana", "apple", "orange"}

Единственное ограничение, что таким образом нельзя создать пустое множество. Вместо этого будет создан пустой словарь:

wrong_empty_set = {}
print(type(wrong_empty_set))

# Вывод
<class "dict">

Для создания пустого множества нужно непосредственно использовать set():

correct_empty_set = set()
print(type(correct_empty_set))

# Вывод
<class "set">

Также в set() можно передать какой-либо объект, по которому можно проитерироваться (Iterable):

color_list = ["red", "green", "green", "blue", "purple", "purple"]
color_set = set(color_list)
print(color_set)

# Вывод (порядок может быть другим):
{"red", "purple", "blue", "green"}

Ещё одна возможность создания множества – это использование set comprehension. Это специальная синтаксическая конструкция языка, которую иногда называют абстракцией множества по аналогии с list comprehension (Списковое включение).

numbers = [1, 2, 2, 2, 3, 3, 4, 4, 5, 6]

# Единственное отличие со списковыми включениями - это
# использование фигурных скобок вместо квадратных
even_numbers = {
    number for number in numbers
    if number % 2 == 0
}
print(even_numbers)

# Вывод (порядок может быть другим):
{2, 4, 6}

Хешируемые объекты

Существует ограничение, что элементами множества (как и ключами словарей) в Python могут быть только так называемые хешируемые (Hashable) объекты. Это обусловлено тем фактом, что внутренняя реализация set основана на хеш-таблицах. Например, списки и словари – это изменяемые объекты, которые не могут быть элементами множеств. Большинство неизменяемых типов в Python (int, float, str, bool, и т.д.) – хешируемые. Неизменяемые коллекции, например tuple, являются хешируемыми, если хешируемы все их элементы.

# Множество кортежей (tuple)
records = {
    ("Москва", 17_200_000), 
    ("Санкт-Петербург", 5_400_000), 
    ("Новосибирск", 1_600_000),
    ("Москва", 17_200_000),
}

for city, population in records:
    print(city)

# Вывод (порядок может быть другим):
Москва
Новосибирск
Санкт-Петербург

Объекты пользовательских классов являются хешируемыми по умолчанию. Но практического смысла чаще всего в этом мало из-за того, что сравнение таких объектов выполняется по их адресу в памяти, т.е. невозможно создать два «равных» объекта.

class City:
    def __init__(self, name: str):
        self.name = name

    def __repr__(self) -> str:
        """ Определим метод __repr__ для наглядности следующих примеров
        """
        return f'City("{self.name}")'

print(City("Moscow") == City("Moscow"))

# Вывод:
False

cities = {City("Moscow"), City("Moscow")}
print(cities)

# Вывод
{City("Moscow"), City("Moscow")}

Скорее всего мы предполагаем, что объекты City("Moscow") должны быть равными, и следовательно в множестве cities должен находиться один объект.
Этого можно добиться, если определить семантику равенства для объектов класса City:

class City:
    def __init__(self, name: str):
        # Атрибут name не должен изменяться, пока объект существует
        # Для простоты пометим этот атрибут как внутренний
        self._name = name

    def __hash__(self) -> int:
        """ Хеш от объекта
        """
        return hash((self._name, self.__class__))

    def __eq__(self, other) -> bool:
        """ Определяем семантику равентсва (оператор ==)
        """
        if not isinstance(other, self.__class__):
            return False
        return self._name == other._name

    def __repr__(self) -> str:
        """ Определим метод __repr__ для наглядности следующих примеров
        """
        return f'City("{self._name}")'

Чтобы протокол хеширования работал без явных и неявных логических ошибок, должны выполняться следующие условия:

  • Хеш объекта не должен изменяться, пока этот объект существует
  • Равные объекты должны возвращать одинаковый хеш

moscow = City("Moscow")
moscow_again = City("Moscow")

print(moscow == moscow_again and hash(moscow) == hash(moscow_again))
# Вывод:
True

# Теперь множество городов работает более логично и интуитивно
cities = {City("Moscow"), City("Kazan"), City("Moscow")}
print(cities)

# Вывод (порядок может быть другим):
{City("Kazan"), City("Moscow")}

Свойства множеств

Тип set в Python является подтипом Collection (про коллекции), из данного факта есть три важных следствия:

  • Определена операция проверки принадлежности элемента множеству
  • Можно получить количество элементов в множестве
  • Множества являются iterable-объектами

Принадлежность множеству

Проверить принадлежит ли какой-либо объект множеству можно с помощью оператора in. Это один из самых распространённых вариантов использования множеств. Такая операция выполняется в среднем за O(1) с теми же оговорками, которые существуют для хеш-таблиц.

tremendously_huge_set = {"red", "green", "blue"}

if "green" in tremendously_huge_set:
    print("Green is there!")
else:
    print("Unfortunately, there is no green...")

# Вывод:
Green is there!

if "purple" in tremendously_huge_set:
    print("Purple is there!")
else:
    print("Unfortunately, there is no purple...")

# Вывод:
Unfortunately, there is no purple...

Мощность множества

Мощность множества – это характеристика множества, которая для конечных множеств просто означает количество элементов в данном множестве. Для бесконечных множеств всё несколько сложнее.

even_numbers = {i for i in range(100) if i % 2 == 0}

# Мощность множества
cardinality = len(even_numbers)
print(cardinality)

# Вывод:
50

Перебор элементов множества

Как уже было отмечено выше, множества поддерживают протокол итераторов, таким образом любое множество можно использовать там, где ожидается iterable-объект.

colors = {"red", "green", "blue"}

# Элементы множества можно перебрать с помощью цикла for
for color in colors:
    print(color)

# Вывод (порядок может быть другим):
red
green
blue

# Множества можно использовать там, где ожидается iterable-объект
color_counter = dict.fromkeys(colors, 1)
print(color_counter)

# Вывод (порядок может быть другим):
{"green": 1, "red": 1, "blue": 1}

Отношения между множествами

Между множествами существуют несколько видов отношений, или другими словами взаимосвязей. Давайте рассмотрим возможные отношения между множествами в этом разделе.

Равные множества

Тут всё довольно просто – два множества называются равными, если они состоят из одних и тех же элементов. Как следует из определения множества, порядок этих элементов не важен.

my_fruits = {"banana", "apple", "orange", "orange"}
your_fruits = {"apple", "apple", "banana", "orange", "orange"}
print(my_fruits == your_fruits)

# Вывод:
True

Непересекающиеся множества

Если два множества не имеют общих элементов, то говорят, что эти множества не пересекаются. Или другими словами, пересечение этих множеств является пустым множеством.

even_numbers = {i for i in range(10) if i % 2 == 0}
odd_numbers = {i for i in range(10) if i % 2 == 1}

# Очевидно, что множества чётных и нечётных чисел не пересекаются
if even_numbers.isdisjoint(odd_numbers):
    print("Множества не пересекаются!")

# Вывод:
Множества не пересекаются!

Подмножество и надмножество

Подмножество множества S – это такое множество, каждый элемент которого является также и элементом множества S. Множество S в свою очередь является надмножеством исходного множества.

# Множество чисел Фибоначчи меньших 100
fibonacci_numbers = {0, 1, 2, 3, 34, 5, 8, 13, 21, 55, 89}

# Множество натуральных чисел меньших 100
natural_numbers = set(range(100))

# Множество чисел Фибоначчи является подмножеством множества 
# натуральных чисел
if fibonacci_numbers.issubset(natural_numbers):
    print("Подмножество!")

# Вывод:
Подмножество!

# В свою очередь множество натуральных чисел является
# надмножеством множества чисел Фибоначчи
if natural_numbers.issuperset(fibonacci_numbers):
    print("Надмножество!")

# Вывод:
Надмножество!

Пустое множество является подмножеством абсолютно любого множества.

empty = set()

# Методы issubset и issuperset могут принимать любой iterable-объект
print(
    empty.issubset(range(100))
    and empty.issubset(["red", "green", "blue"])
    and empty.issubset(set())
)

# Вывод:
True

Само множество является подмножеством самого себя.

natural_numbers = set(range(100))

if natural_numbers.issubset(natural_numbers):
    print("Подмножество!")

# Вывод:
Подмножество!

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

Рассмотрим основные операции, опредяляемые над множествами.

Объединение множеств

Объединение множеств – это множество, которое содержит все элементы исходных множеств. В Python есть несколько способов объединить множества, давайте рассмотрим их на примерах.

my_fruits = {"apple", "orange"}
your_fruits = {"orange", "banana", "pear"}

# Для объединения множеств можно использовать оператор `|`,
# оба операнда должны быть объектами типа set
our_fruits = my_fruits | your_fruits
print(our_fruits)

# Вывод (порядок может быть другим):
{"apple", "banana", "orange", "pear"}

# Также можно использовать ментод union.
# Отличие состоит в том, что метод union принимает не только
# объект типа set, а любой iterable-объект
you_fruit_list: list = list(your_fruits)
our_fruits: set = my_fruits.union(you_fruit_list)
print(our_fruits)

# Вывод (порядок может быть другим):
{"apple", "banana", "orange", "pear"}

Добавление элементов в множество

Добавление элементов в множество можно рассматривать как частный случай объединения множеств за тем исключением, что добавление элементов изменяет исходное множество, а не создает новый объект. Добавление одного элемента в множество работает за O(1).

colors = {"red", "green", "blue"}

# Метод add добаляет новый элемент в множество
colors.add("purple")
# Добавление элемента, который уже есть в множестве, не изменяет
# это множество
colors.add("red")
print(colors)

# Вывод (порядок может быть другим):
{"red", "green", "blue", "purple"}

# Метод update принимает iterable-объект (список, словарь, генератор и т.п.)
# и добавляет все элементы в множество
numbers = {1, 2, 3}
numbers.update(i**2 for i in [1, 2, 3])
print(numbers)

# Вывод (порядок может быть другим):
{1, 2, 3, 4, 9}

Пересечение множеств

Пересечение множеств – это множество, в котором находятся только те элементы, которые принадлежат исходным множествам одновременно.

def is_prime(number: int) -> bool:
    """ Возвращает True, если number - это простое число
    """
    assert number > 1
    return all(number % i for i in range(2, int(number**0.5) + 1))

def is_fibonacci(number: int) -> bool:
    """ Возвращает True, если number - это число Фибоначчи
    """
    assert number > 1
    a, b = 0, 1
    while a + b < number:
        a, b = b, a + b
    return a + b == number

# Множество простых чисел до 100
primes = set(filter(is_prime, range(2, 101)))

# Множество чисел Фибоначчи до 100
fibonacci = set(filter(is_fibonacci, range(2, 101)))

# Множество простых чисел до 100, которые одновременно являются
# числами Фибоначчи
prime_fibonacci = primes.intersection(fibonacci)

# Или используя оператор `&`, который определён для множеств
prime_fibonacci = fibonacci & primes

print(prime_fibonacci)

# Вывод (порядок может быть другим):
{2, 3, 5, 13, 89}

При использовании оператора & необходимо, чтобы оба операнда были объектами типа set. Метод intersection, в свою очередь, принимает любой iterable-объект. Если необходимо изменить исходное множество, а не возращать новое, то можно использовать метод intersection_update, который работает подобно методу intersection, но изменяет исходный объект-множество.

Разность множеств

Разность двух множеств – это множество, в которое входят все элементы первого множества, не входящие во второе множество.

i_know: set = {"Python", "Go", "Java"}
you_know: dict = {
    "Go": 0.4, 
    "C++": 0.6, 
    "Rust": 0.2, 
    "Java": 0.9
}

# Обратите внимание, что оператор `-` работает только
# для объектов типа set
you_know_but_i_dont = set(you_know) - i_know
print(you_know_but_i_dont)

# Вывод (порядок может быть другим):
{"Rust", "C++"}

# Метод difference может работать с любым iterable-объектом,
# каким является dict, например
i_know_but_you_dont = i_know.difference(you_know)
print(i_know_but_you_dont)

# Вывод:
{"Python"}

Удаление элементов из множества

Удаление элемента из множества можно рассматривать как частный случай разности, где удаляемый элемент – это одноэлементное множество. Следует отметить, что удаление элемента, как и в аналогичном случае с добавлением элементов, изменяет исходное множество. Удаление одного элемента из множества имеет вычислительную сложность O(1).

fruits = {"apple", "orange", "banana"}

# Удаление элемента из множества. Если удаляемого элемента
# нет в множестве, то ничего не происходит
fruits.discard("orange")
fruits.discard("pineapple")
print(fruits)

# Вывод (порядок может быть другим):
{"apple", "banana"}

# Метод remove работает аналогично discard, но генерирует исключение,
# если удаляемого элемента нет в множестве
fruits.remove("pineapple")  # KeyError: "pineapple"

Также у множеств есть метод differenсe_update, который принимает iterable-объект и удаляет из исходного множества все элементы iterable-объекта. Этот метод работает аналогично методу difference, но изменяет исходное множество, а не возвращает новое.

numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
even_numbers_under_100 = (i for i in range(1, 101) if i % 2 == 0)
numbers.difference_update(even_numbers_under_100)
print(numbers)

# Вывод (порядок может быть другим):
{1, 3, 5, 7, 9}

Симметрическая разность множеств

Симметрическая разность множеств – это множество, включающее все элементы исходных множеств, не принадлежащие одновременно обоим исходным множествам. Также симметрическую разность можно рассматривать как разность между объединением и пересечением исходных множеств.

non_positive = {-3, -2, -1, 0}
non_negative = {0, 1, 2, 3}

# Обратите внимание, что оператор `^` может применяться
# только для объектов типа set
non_zero = non_positive ^ non_negative
print(non_zero)

# Вывод (порядок может быть другим):
{-1, -2, -3, 1, 2, 3}

Как видно из примера выше, число 0 принадлежит обоим исходным множествам, и поэтому оно не входит в результирующее множество. Для операции симметрической разности, помимо оператора ^, также существует два специальных метода – symmetric_difference и symmetric_difference_update. Оба этих метода принимают iterable-объект в качестве аргумента, отличие же состоит в том, что symmetric_difference возвращает новый объект-множество, в то время как symmetric_difference_update изменяет исходное множество.

non_positive = {-3, -2, -1, 0}
non_negative = range(4)

non_zero = non_positive.symmetric_difference(non_negative)
print(non_zero)

# Вывод (порядок может быть другим):
{-1, -2, -3, 1, 2, 3}

# Метод symmetric_difference_update изменяет исходное множество
colors = {"red", "green", "blue"}
colors.symmetric_difference_update(["green", "blue", "yellow"])
print(colors)

# Вывод (порядок может быть другим):
{"red", "yellow"}

Заключение

Я надеюсь, мне удалось показать, что Python имеет очень удобные встроенные средства для работы с множествами. На практике это часто позволяет сократить количество кода, сделать его выразительнее и легче для восприятия, а следовательно и более поддерживаемым. Я буду рад, если у вас есть какие-либо конструктивные замечания и дополнения.

Полезные ссылки

Множества (Статья на Википедии)
Документация по типу set
Iterable-объекты (Глоссарий Python)
Hashable-объекты (Глоссарий Python)
Sets in Python
Set Theory: the Method To Database Madness

If you don’t have Python 2.6 or higher, the alternative is to write an explicit for loop:

def set_list_intersection(set_list):
  if not set_list:
    return set()
  result = set_list[0]
  for s in set_list[1:]:
    result &= s
  return result

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print set_list_intersection(set_list)
# Output: set([1])

You can also use reduce:

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print reduce(lambda s1, s2: s1 & s2, set_list)
# Output: set([1])

However, many Python programmers dislike it, including Guido himself:

About 12 years ago, Python aquired lambda, reduce(), filter() and map(), courtesy of (I believe) a Lisp hacker who missed them and submitted working patches. But, despite of the PR value, I think these features should be cut from Python 3000.

So now reduce(). This is actually the one I’ve always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what’s actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it’s better to write out the accumulation loop explicitly.

In this article, a List of sets is given our task is to write a program to perform their intersection using Python.

Examples of finding the intersection of multiple sets

Input : test_list = [{5, 3, 6, 7}, {1, 3, 5, 2}, {7, 3, 8, 5}, {8, 4, 5, 3}]
Output : {3, 5}
Explanation : 3 and 5 is present in all the sets.

Method 1: Using a Logical operator

This is the simplest method to get the intersection of multiple sets using the Python logical operator

Python3

set_1 = {21, 10, 5, 11, 12}

set_2 = {5, 21, 3, 8, 9}

set_3 = {1, 21, 5, 3, 4, 5}

set4 = set1 & set2 & set3

print(set4)

Output:

{21, 5}

Method 2: Using intersection() + * operator

In this, we will perform tasks to get intersections using intersection() and the * operator is used to pack all the sets together.

Python3

test_list = [{5, 3, 6, 7}, {1, 3, 5, 2}, {7, 3, 8, 5}, {8, 4, 5, 3}]

print("The original list is : " + str(test_list))

res = set.intersection(*test_list)

print("Intersected Sets : " + str(res))

Output:

The original list is : [{3, 5, 6, 7}, {1, 2, 3, 5}, {8, 3, 5, 7}, {8, 3, 4, 5}]
Intersected Sets : {3, 5}

Method 3: Using reduce() + and_ operator

In this, we will perform intersection using and_ operator and Python reduce() does the task of getting all the sets packed together for the required operation.

Python3

from operator import and_

from functools import reduce

test_list = [{5, 3, 6, 7}, {1, 3, 5, 2}, {7, 3, 8, 5}, {8, 4, 5, 3}]

print("The original list is : " + str(test_list))

res = set(reduce(and_, test_list))

print("Intersected Sets : " + str(res))

Output:

The original list is : [{3, 5, 6, 7}, {1, 2, 3, 5}, {8, 3, 5, 7}, {8, 3, 4, 5}]
Intersected Sets : {3, 5}

Last Updated :
24 Mar, 2023

Like Article

Save Article

Курс по Python: https://stepik.org/course/100707

На этом занятии мы с
вами будем говорить об операциях над ними – это:

  • пересечение
    множеств;

  • объединение
    множеств;

  • вычитание
    множеств;

  • вычисление
    симметричной разности.

Для простоты
зададим два множества с числами:

setA = {1, 2, 3, 4}
setB = {3, 4, 5, 6, 7}

На их основе
можно построить третье множество, как результат пересечения этих двух:

На выходе
получаем новое множество, состоящее из значений, общих для множеств setA и setB. Это и есть
операция пересечения двух множеств. При этом, исходные множества остаются без
изменений. Здесь именно создается новое множество с результатом выполнения этой
операции.

Разумеется,
чтобы в дальнейшем в программе работать с полученным результатом, его нужно
сохранить через какую-либо переменную, например, так:

Также допустима
запись в виде:

это будет
эквивалент строчки:

То есть, мы
вычисляем результат пересечения и сохраняем его в переменной seta и, как бы,
меняем само множество setA.

А вот если взять
множество:

которое не имеет
общих значений с другим пересекающимся множеством, то результатом:

будет пустое
множество.

Обычно, на
практике используют оператор пересечения &, но вместо него можно
использовать специальный метод:

setA = {1, 2, 3, 4}
setB = {3, 4, 5, 6, 7}
setA.intersection(setB)

Результат будет
тем же, на выходе получим третье множество, состоящее из общих значений
множеств setA и setB. Если же мы
хотим выполнить аналог операции:

то для этого
следует использовать другой метод:

setA.intersection_update(setB)

В результате,
меняется само множество setA, в котором хранятся значения
пересечения двух множеств.

Вот такие
способы вычислений пересечения множеств существуют в Python.

Объединение множеств

Следующая
операция – это объединение двух множеств. Она записывается, так:

setA = {1, 2, 3, 4}
setB = {3, 4, 5, 6, 7}
setA | setB

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

Или же можно
воспользоваться эквивалентным методом:

который
возвращает множество из объединенных значений. При этом, сами множества
остаются без изменений.

Операцию
объединения можно записать также в виде:

Тогда уже само
множество setA будет хранить
результат объединения двух множеств, то есть, оно изменится. Множество setB останется без
изменений.

Вычитание множеств

Следующая
операция – это вычитание множеств. Например, для множеств:

setA = {1,2,3,4}
setB = {3,4,5,6,7}

операция

возвратит новое
множество, в котором из множества setA будут удалены
все значения, повторяющиеся в множестве setB:

{1, 2}

Или, наоборот,
если из множества setB вычесть множество setA:

то получим
значения из которых исключены величины, входящие в множество setA.

Также здесь
можно выполнять эквивалентные операции:

setA -= setB
setB -= setA

В этом случае
переменные setA и setB будут ссылаться
на соответствующие результаты вычитаний.

Симметричная разность

Наконец,
последняя операции над множествами – симметричная разность, возвращает
множество, состоящее из неповторяющихся значений обоих множеств. Реализуется
она следующим образом:

setA = {1,2,3,4}
setB = {3,4,5,6,7}
setA ^ setB

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

Сравнение множеств

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

Предположим,
имеются два таких множества:

setA = {7, 6, 5, 4, 3}
setB = {3, 4, 5, 6, 7}

И мы хотим
узнать, равны они или нет. Для этого, используется уже знакомый нам оператор
сравнения на равенство:

Увидим значение True (истина).
Почему? Дело в том, что множества считаются равными, если все элементы,
входящие в одно из них, также принадлежат другому и мощности этих множеств
равны (то есть они содержат одинаковое число элементов). Наши множества setA и
setB удовлетворяют этим условиям.

Соответственно,
противоположное сравнение на не равенство, выполняется, следующим образом:

Следующие два
оператора сравнения на больше и меньше, фактически, определяют, входит ли одно
множество в другое или нет.

Например,
возьмем множества

setA = {7, 6, 5, 4, 3}
setB = {3, 4, 5}

тогда операция

вернет True, а операция

значение False. Но, если хотя
бы один элемент множества setB не будет принадлежать множеству setA:

то обе операции
вернут False. Для равных множеств

setA = {7, 6, 5, 4, 3}
setB = {3, 4, 5, 6, 7}

обе операции
также вернут False. Но вот такие
операторы:

setA <= setB
setA >= setB

вернут True.

Я, думаю, из
этих примеров понятно, как выполняется сравнение множеств между собой.

Для закрепления
этого материала, как всегда, пройдите практические задания и, затем, дальше –
на покорение новых вершин языка Python. Буду вас ждать на следующем
уроке.

Курс по Python: https://stepik.org/course/100707

Видео по теме

Понравилась статья? Поделить с друзьями:
  • Как найти сохраненный документ в pdf
  • Как исправить recovery на ноутбуке
  • Как найти подземный гриб
  • Инстаграм как найди друзей
  • Карта памяти на ксиаоми как найти