Лучший способ найти пересечение нескольких множеств?

У меня есть список наборов:

setlist = [s1,s2,s3...]

Я хочу s1 ∩ s2 ∩ s3...

Я могу записать функцию, чтобы сделать это путем выполнения серии попарно s1.intersection(s2), и т.д.

Существует ли рекомендуемый, лучше, или встроенный путь?

231
задан martineau 2 August 2017 в 09:37
поделиться

4 ответа

Начиная с версии Python 2.6, вы можете использовать несколько аргументов для set.intersection () , например

u = set.intersection(s1, s2, s3)

Если наборы находятся в список, это переводится как:

u = set.intersection(*setlist)

где * a_list - расширение списка

405
ответ дан 23 November 2019 в 03:37
поделиться

Начиная с версии 2.6, set.intersection принимает произвольное количество итераций.

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s3 = set([2, 4, 6])
>>> s1 & s2 & s3
set([2])
>>> s1.intersection(s2, s3)
set([2])
>>> sets = [s1, s2, s3]
>>> set.intersection(*sets)
set([2])
62
ответ дан 23 November 2019 в 03:37
поделиться

Если у вас нет Python 2.6 или выше, альтернативой является создание явного цикла for:

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])

Вы также можете использовать reduce :

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

Однако многим программистам Python он не нравится , включая самого Гвидо :

Около 12 лет назад Python приобрел lambda, reduce (), filter () и map () благодаря (как мне кажется) хакеру Lisp, который пропустил их и представил рабочие патчи. Но, несмотря на значение PR, я думаю, что эти функции следует убрать из Python 3000.

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

11
ответ дан 23 November 2019 в 03:37
поделиться

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

def multiple_set_intersection(*sets):
    """Return multiple set intersection."""
    try:
        return set.intersection(*sets)
    except TypeError: # this is Python < 2.6 or no arguments
        pass

    try: a_set= sets[0]
    except IndexError: # no arguments
        return set() # return empty set

    return reduce(a_set.intersection, sets[1:])

Гвидо может не понравиться reduce, но мне он вроде как нравится :)

1
ответ дан 23 November 2019 в 03:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: