Как я могу создать набор наборов в Python?

126

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

Начиная с пустого набора xx:

xx = set([])
# Now we have some other set, for example
elements = set([2,3,4])
xx.add(elements)

но я получаю

TypeError: unhashable type: 'list'

или

TypeError: unhashable type: 'set'

Возможно ли иметь набор наборов в Python?

Я имею дело с большой коллекцией наборов, и я не хочу иметь возможность иметь дело с дублирующимися наборами (набор B наборов A1, A2, ...., An "отменил бы" два набора, если Ai = Aj)

Matt
источник

Ответы:

121

Python жалуется, потому что внутренние setобъекты изменчивы и, следовательно, не могут быть хешированы. Решение - использовать frozensetдля внутренних наборов, чтобы указать, что вы не собираетесь их изменять.

a3nm
источник
59

Люди уже упоминали, что вы можете сделать это с помощью frozenset () , поэтому я просто добавлю код, как этого добиться:

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

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

вы можете создать свой набор следующим образом:

t1 = set(frozenset(i) for i in t)
Сальвадор Дали
источник
9
или вы можете использовать карту! set(map(frozenset, t))
Мэтт Додж
18

Использовать frozensetвнутрь.

Игнасио Васкес-Абрамс
источник
9
Возможно, вы могли бы дать несколько указаний об изменяемых / неизменяемых объектах в Python, поскольку он новичок?
Сет Джонсон,
2
@Seth: Я мог бы, но изменчивость не имеет значения.
Игнасио Васкес-Абрамс,
Огромное спасибо! Просто читаю сейчас re: mutability. Похоже, что набор списков тоже может работать, но Frozenset, кажется, справляется. Еще раз спасибо!
Мэтт
@Ignacio Я думал, что элементы в наборах и ключи в dicts должны быть хешируемыми и, следовательно, неизменными.
Сет Джонсон,
7
Хешабельность и изменчивость не обязательно исключают друг друга. Так уж получилось, что большинство основных типов Python имеют общий шаблон.
Игнасио Васкес-Абрамс,
3

Так что у меня была точно такая же проблема. Я хотел создать структуру данных, которая работает как набор наборов. Проблема в том, что наборы должны содержать неизменяемые объекты. Итак, вы можете просто сделать его набором кортежей. У меня это сработало!

A = set()
A.add( (2,3,4) )##adds the element
A.add( (2,3,4) )##does not add the same element
A.add( (2,3,5) )##adds the element, because it is different!
tremb
источник
22
В кортежах имеет значение порядок элементов. Таким образом A.add( (4,3,2)); A.add((2,4,3)); A.add((2,3,4))добавит три различных элемента, в то время как оригинальный вопрос о «множестве множеств», что означает , что (2,3,4), (4,3,2), (2,4,3)являются одинаковыми.
Борис Горелик
1

По состоянию на 2020 год официальная документация Python рекомендует использовать frozensetдля представления наборов.

AtilioA
источник
1
Вау, это очень интересно, учитывая, что PEP 416 (замороженный диктатор) не был принят и был предложен в 2012 году.
NikoNyrh,