set和frozenset在实现上的差异

时间:2013-07-15 02:43:03

标签: python

我在这个链接上检查了set是可变的https://docs.python.org/3/library/stdtypes.html#frozenset,而frozenset是不可变的,因此可以清除。那么如何在python中实现集合以及元素查找时间是多少?实际上我有一个元组列表[(1,2),(3,4),(2,1)],其中元组中的每个条目都是一个id,我想从这个列表中创建一个set / frozenset。在这种情况下,集合应包含(1,2,3,4)作为元素。我可以使用frozenset从元组列表中逐个插入元素,或者我只能使用一组吗?

3 个答案:

答案 0 :(得分:7)

您可以从生成器表达式或其他可迭代实例化冻结集。在完成实例化之前,它不是不可变的。

>>> L = [(1,2),(3,4),(2,1)]
>>> from itertools import chain
>>> frozenset(chain.from_iterable(L))
frozenset([1, 2, 3, 4])

Python3.3还有一个优化,当用作in运算符的右侧时,将{1,2,3,4}等集合文字转换为预先计算的frozensets。

答案 1 :(得分:5)

集合和frozensets以与哈希表相同的方式实现。 (为什么他们还要求他们的元素实现__hash__?)事实上,如果你看Objects/setobject.c,他们几乎可以共享所有代码。这意味着只要哈希冲突不会失控,查找和删除就是O(1),插入就是分摊O(1)。

创建冻结集的常用方法是使用其他迭代函数对其进行初始化。正如gnibbler建议的那样,这里最合适的可能是itertools.chain.from_iterable

>>> L = [(1,2),(3,4),(2,1)]
>>> from itertools import chain
>>> frozenset(chain.from_iterable(L))
frozenset([1, 2, 3, 4])

答案 2 :(得分:-2)

关于你的第一个问题,我还没有真正检查过源代码,但似乎可以安全地假设集合需要包含可散列类型的对象,它是使用哈希表实现的,并且因此,它的查找时间为O(1)。

关于你的第二个问题,你不能逐个将这些元素插入frozenset(显然,因为它是不可变的),但是没有理由使用一个集合;只是从组成值的列表(或其他可迭代的)构造它,例如,像这样:

data = [(1, 2), (3, 4), (2, 1)]
result = frozenset(reduce(list.__add__, [list(x) for x in data], []))