首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Python中设置一组集合?

如何在Python中设置一组集合?
EN

Stack Overflow用户
提问于 2016-05-09 07:00:40
回答 3查看 19.8K关注 0票数 19

在Python中,没有对异构数据结构的完全支持。例如,这将失败:

代码语言:javascript
运行
复制
set(set(1,2),set(2,3))

处理集合的最好方法是什么?

EN

回答 3

Stack Overflow用户

发布于 2016-05-09 07:04:20

使用frozenset

代码语言:javascript
运行
复制
>>> set([frozenset([1,2]), frozenset([2,3])])
set([frozenset([1, 2]), frozenset([2, 3])])

要表示一组集合,内部集合必须是Python对象,因为集合的元素必须是可散列的(的所有不可变内置对象都是可散列的)。frozenset是不可变的,而set是可变的。

票数 34
EN

Stack Overflow用户

发布于 2016-05-09 07:04:14

您不能拥有通常意义上的一组集合,但如果您可以使用frozenset对象,那么它就可以工作:

代码语言:javascript
运行
复制
>>> set([set([1,2]), set([3,4])])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'

这是可行的:

代码语言:javascript
运行
复制
>>> set([frozenset([1,2]), frozenset([3,4])])
set([frozenset([1, 2]), frozenset([3, 4])])
票数 5
EN

Stack Overflow用户

发布于 2016-05-09 07:33:20

一组集合不能工作的原因是很好的。想象一下(用伪代码):

代码语言:javascript
运行
复制
a = set(range(5))   # {0, 1, 2, 3, 4}
b = set(range(5, 10))  # {5, 6, 7, 8, 9}
c = set(range(5))  # {0, 1, 2, 3, 4}
# we've now created a set of sets, and then will drop `c` because it's redundant
d = set([a, b, c])  # {{0, 1, 2... }, {5, 6, 7...}}
# now we've changed a value inside the set, suddenly everything changes
a.add(6)     # {{0, 1, 2..., 6}, {5, 6, 7...}}
# now we can re-add `c`
d.add(c)    # {{0, 1, 2..., 6}, {5, 6, 7...}, {0, 1, 2...}}

除了元素突然消失的奇怪行为之外,如果元素是可变的,那么它们的行为也会不同,此外还缺乏基于散列的查找。

set实现与dict实现非常相似,可以在here中找到。如果一个集合包含一个给定的键,这就是实现。注意它是如何计算对象的散列的,找到第一个匹配项,然后从散列中进行查找?

代码语言:javascript
运行
复制
static int
set_contains_key(PySetObject *so, PyObject *key)
{
    long hash;
    setentry *entry;

    if (!PyString_CheckExact(key) ||
        (hash = ((PyStringObject *) key)->ob_shash) == -1) {
        hash = PyObject_Hash(key);
        if (hash == -1)
            return -1;
    }
    entry = (so->lookup)(so, key, hash);
    if (entry == NULL)
        return -1;
    key = entry->key;
    return key != NULL && key != dummy;
}

现在,如果我们修改上面示例中的a,我们如何执行查找?唯一的解决方案是逐项查找,其时间复杂度为O(n)。

幸运的是,上面显示了一个简单的解决方案:一个不可变的集合。幸运的是,Python甚至有这个内置的frozenset

使用冻结集,因为它是不可变的,所以可以计算散列,既防止了意外行为,又恢复了O(1)查找。

在这种情况下,我们可以执行以下操作:

代码语言:javascript
运行
复制
a = frozenset(range(5))
b = frozenset(range(5, 10))
c = frozenset(range(5))
d = set([a, b, c])

现在,d将允许对单独的项目进行成员查找,只使用离散的容器,因为冻结集成员是不可变的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37105696

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档