Как найти пересечение множеств: Пересечение и объединение множеств: что это, свойства операций с множествами

2

Пересечение нескольких множеств в одну строчку

Сегодня на паре по программированию для журналистики данных мы столкнулись с такой задачей: есть список множеств, нужно найти пересечение их всех. Как это проще всего сделать в Python? Оказывается, у этой задачи есть решение в одну строчку.

Собственно, дело было так. Мы смотрели на данные по госзакупкам через API сайта clearspending.ru. Там у каждого контракта куча разных атрибутов. Как видно из следующих примеров, наборы атрибутов (в данном случае, ключей в словаре) у разных контрактов различаются. Мы хотели найти такие атрибуты, которые есть у всех контрактов.

In [2]:

import requests
# пример из документации
# https://github.com/idalab/clearspending-examples/wiki/Описание-API-Контракты
entrypoint = "http://openapi.clearspending.ru/restapi/v3/contracts/search/"
r = requests.get(entrypoint, {'customerregion': '05', 'sort':'-price'})
response = r.json()
contracts = response['contracts']['data']

In [3]:

contracts[0]. keys()

Out[3]:

dict_keys(['finances', 'documentBase', 'versionNumber', 'mongo_id', 'suppliers', 'placingWayCode', 'contractUrl', 'foundation', 'products', 'scan', 'fileVersion', 'contractProcedure', 'economic_sectors', 'signDate', 'fz', 'currentContractStage', 'printFormUrl', 'price', 'protocolDate', 'number', 'regNum', 'currentContractStage_raw', 'loadId', 'attachments', 'customer', 'placing', 'regionCode', 'id', 'currency', 'singleCustomerReason', 'execution', 'publishDate', 'schemaVersion'])

In [4]:

contracts[1].keys()

Out[4]:

dict_keys(['signDate', 'versionNumber', 'mongo_id', 'finances', 'contractUrl', 'foundation', 'misuses', 'regionCode', 'fileVersion', 'documentBase', 'fz', 'currentContractStage', 'price', 'placing', 'number', 'products', 'publishDate', 'customer', 'regNum', 'suppliers', 'id', 'currency', 'execution', 'loadId'])

По такому поводу я рассказал про множества в Python (давно откладывал это — к слову не приходилось) и написал такой код.

In [5]:

fields = set(contracts[0])
# сделали множество из списка ключей первого контракта
# здесь словарь contracts[0] рассматривается как iterable
# а в этом случае он итерирует свои ключи
# поэтому .keys() дописывать не нужно
for contract in contracts[1:]:
    fields.intersection_update(contract)
    # пересечь множество fields с множеством, полученным из списка ключей
    # очередного контракта и результат записать в fields
    # иными словами, выкинуть из fields те элементы, которых нет в
    # списке ключей очередного контракта
fields

Out[5]:

{'currency',
 'customer',
 'fileVersion',
 'fz',
 'id',
 'loadId',
 'mongo_id',
 'number',
 'price',
 'products',
 'publishDate',
 'regNum',
 'regionCode',
 'versionNumber'}

Он мне перестал нравиться ещё до того, как я закончил его писать. Ну, право дело, ведь когда нам нужно сложить числа в списке, мы не пишем цикл — мы просто вызываем функцию sum(). Должно, наверное, и для множеств быть что-то похожее? На паре тратить время на поиски не хотелось, но, придя домой, я всё же решил найти ответ на этот вопрос. Оказывается, есть очень просто решение!

In [6]:

fields = set.intersection(*[set(contract) for contract in contracts])
fields

Out[6]:

{'currency',
 'customer',
 'fileVersion',
 'fz',
 'id',
 'loadId',
 'mongo_id',
 'number',
 'price',
 'products',
 'publishDate',
 'regNum',
 'regionCode',
 'versionNumber'}

Дело в том, что set.intersection() принимает на вход любое количество аргументов! С помощью спискового включения мы делаем список множеств, составленных из ключей каждого контракта, затем звёздочкой «распаковываем» этот список в набор аргументов

set.intersection() — вжух — и всё готово!

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

UPD. После подсказки @rusorrow о том, что .keys() не нужен при создании множества, я подумал, что можно было бы сделать ещё короче: с помощью map — мне кажется, что так даже лучше — это, пожалуй, тот случай, когда map упрощает код по сравнению со списочными включениями.

In [7]:

set.intersection(*map(set, contracts))

Out[7]:

{'currency',
 'customer',
 'fileVersion',
 'fz',
 'id',
 'loadId',
 'mongo_id',
 'number',
 'price',
 'products',
 'publishDate',
 'regNum',
 'regionCode',
 'versionNumber'}

Tweet

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

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

Определение:

Для двух множеств A и B пересечением является множество, содержащее элементы или объекты, принадлежащие A и B одновременно.

Мы пишем A ∩ B

По сути, мы находим A ∩ B, ища все элементы A и B, которые являются общими. Далее разберем на примерах.

Пример #1 .

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

Пусть A = {  1 апельсин , 1 ананас, 1 банан,

1 яблоко } и B = { 1 ложка, 1 апельсин , 1 нож, 1 вилка, 1 яблоко }

A

= {1 апельсин, 1 яблоко}

Пример #2 .

Найдите пересечение A и B, а затем постройте диаграммы Венна.

А = { б , 1, 2, 4 , 6 } и B = { 4 , a, b , c, d, f }

A ∩ B = { 4, b } 

4 9 Пример 3 .

 A = { x / x число больше 4 и меньше 8 }

 B = { x / x положительное число меньше 7 }

 A = { 5 , 6 , 7 } и B = { 1, 2, 3, 4, 5 , }

 A ∩ B = { 5, 6 }

Или A ∩ B = { x / x число больше 4 и меньше чем 7 }

Пример #4 .

 A = {x/x — страна в Азии}

 B = {x/x — страна в Африке}

Поскольку в Азии и Африке нет одинаковых стран, пересечение пусто.

 A ∩ B = { } 

 Пример №5 .

А = {#, %, &, *, $}

B = { }

Этот пример тонкий! Поскольку пустое множество входит в любое множество, оно также входит в A, хотя вы этого не видите.

Таким образом, пустое множество — это единственное, что общего между множествами A и B.

А ∩ В = { } 

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

Определение объединения трех множеств:

Пересечением трех множеств A, B и C называется множество, содержащее элементы или объекты, принадлежащие A, B и C одновременно.

Мы пишем A ∩ B ∩ C

По сути, мы находим A ∩ B ∩ C, ища все элементы, которые A, B и C имеют общие.

A = { # , 1, 2, 4 , 6}, B = { # , a, b, 4 , c} и C = A = { #

, %, &, * , $, 4 }

A ∩ B ∩ C = { 4 , # }

На приведенном ниже графике показана заштрихованная область пересечения двух множеств

На приведенном ниже графике показана заштрихованная область пересечения трех множеств

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

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

  1. Треугольник 30-60-90

    3 апреля, 23 17:08

    Что такое треугольник 30-60-90? Определение, доказательство, площадь и простые примеры из реальной жизни.

    Подробнее

  2. Расчет условной вероятности с помощью таблицы непредвиденных обстоятельств

    29, 23 марта 10:19

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

    Подробнее

Дискретная математика — Нахождение пересечения трех множеств

спросил

2 года, 2 месяца назад

Изменено 2 года, 2 месяца назад

Просмотрено 6к раз

$\begingroup$

80 учащихся спросили, нравятся ли им математика, естественные науки или гуманитарные науки. 24 учащимся не нравился ни один из предметов, 9понравилась математика только , 16 нравились науки только , 9 нравились гуманитарные науки только , 12 нравились математика и гуманитарные науки, 7 любили математику и естественные науки и 9 любили гуманитарные и наука.

а) Сколько учеников любят все три предмета?

б) Сколько учеников любят математику или естествознание?

в) Сколько студентов не любят гуманитарные науки?

Вот диаграмма Венна, отображающая данную информацию:


а) нахождение пересечения множеств M, S и H

|M∩S∩H|=|M∪S∪H|−(|M|+|S|+|H|)+|M∩S|+|M∩H|+|S∩H|

-2 |M∩S∩H|= (80 — 24) — (9 + 16 + 9) — (12 + 7 + 9)

-2 |M∩S∩H|= 56 — 34 — 28

-2 |M∩S∩H|= 22 — 28

-2 |M∩S∩H|= -6

|M∩S∩H|= 3


Не могу б) или в) потому что, когда я говорю, что пересечение равно 3, все остальные числа на диаграмме Венна меняются (очевидно). Например, если пересечение равно 3, то количество людей, которым нравятся математика и естествознание, = 4 (7 — 3 ) и количество людей, которым нравятся математика и гуманитарные науки = 9 (12 — 3 ). Но когда я складываю новые числа (3 + 9 + 4), я получаю 16, и я не могу сделать 9 — 16 (что равно -5, ОТРИЦАТЕЛЬНОЕ ЧИСЛО!!!). Может кто-нибудь, пожалуйста, дайте мне знать, что у меня есть сделано неправильно, и как, черт возьми, я должен вычислить пересечение трех наборов?! Любая помощь будет принята с благодарностью.

  • дискретная математика
  • элементарная теория множеств

$\endgroup$

$\begingroup$

Итак, ваша первая проблема заключается в том, что ваша диаграмма Венна не отображает данную информацию, как вы заметили в конце. Это сбивает вас с толку, несмотря на то, что ваше решение по существу правильное, хотя и несколько странно рассчитано (хотя я понятия не имею, почему вы пытаетесь вычислить 9–16 долларов: вам не нужно настраивать внешние значения, потому что они уже в ваша диаграмма Венна правильно; действительно, они даны в вопросе).

Обозначим количество учеников, которым нравятся все три предмета, $x$. Тогда ваша реальная диаграмма Венна выглядит так:

Теперь, суммируя все эти значения, мы видим, что 80 долларов = 24 + 9 + 16 + 9 + 7 — х + 9 — х + 12 — х + х = 86 — 2х$, и поэтому 2х долларов = 6 $ и $x = 3$. Таким образом, полная диаграмма Венна выглядит так:

Теперь мы можем решить вопросы, просто прочитав диаграмму.

$\endgroup$

1

$\begingroup$

Вы упускаете из виду, что 7$, которые любят математику и естественные науки, и 12$, которые любят математику и гуманитарные науки, и 9$$ кто любит гуманитарные науки и науки, ПЕРЕКРЫВАЮТ и каждая из этих групп включает тех, кому нравятся все три.

Вы предположили, что это все отдельные и каждая группа исключила те $?$, которым понравились все три.

====

Используйте это изображение вместо

Когда вы говорите $12$ как математика и гуманитарные науки, это двусмысленно относительно того, имеется ли в виду наличие $12$, которые любят математику, гуманитарные науки и не любят науку. Или если есть 12$, которые любят математику и гуманитарные науки и могут любить или не любить науку.

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

Но если вы интерпретируете это вторым способом (что является логическим, буквальным и математическим способом интерпретации этого; если вам говорят, что они любят математику и гуманитарные науки, это означает, что все, кто любит математику и гуманитарные науки, независимо от того, что еще они могут или может не нравиться) тогда, если есть $?$, которым нравятся все три, то есть $12$, которым нравятся математика и гуманитарные науки, а может и не нравиться наука; и есть $12-?$, которые любят математику и гуманитарные науки и не любят науку.

Другой способ просмотра:

Но здесь должно быть ясно, что области $7,12,9$ перекрываются.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *