【问题标题】:set of sets and "in" operator [duplicate]集合和“in”运算符[重复]
【发布时间】:2021-07-18 07:12:40
【问题描述】:

我正在做一些编码练习,最后我使用了 setfrozensets。 代码如下:

cities = 4
roads = [[0, 1], [1, 2], [2, 0]]
roads = set([frozenset(road) for road in roads])
    
output = []
    
for i in range(cities-1):
    for j in range(i+1, cities):
        if set([i,j]) not in roads:
            output.append([i,j])

如您所见,嵌套的for 中的if 测试集合中是否存在集合。 但是,据我了解,在这种情况下,哈希值需要与 in 运算符一起使用。

如果我将set([i,j]) 替换为[i,j],我会收到以下错误:

TypeError: unhashable type: 'list'

所以,这是我的问题:为什么它适用于集合,它不是(据我所知)可散列而不适用于列表? 它不应该也抛出错误吗,我错过了什么?

【问题讨论】:

  • @Hcaertnit:不是这样。这“有点”微妙。
  • frozensets 可散列的,因为它们是不可变的。

标签: python set


【解决方案1】:

从我对 CPython 源代码的阅读看来,contains 的测试检查是否在集合中找到了密钥;如果不是,并且如果密钥是set 对象,则尝试将密钥转换为frozenset,然后测试该密钥。像remove 这样的操作也存在相同的行为,如下所示:

>>> s = set([frozenset([1,2])])
>>> s
{frozenset({1, 2})}
>>> s.remove(set([1,2]))
>>> s
set()

解释器中有问题的代码是Objects/setobject.c 中的set_contains() 函数。

【讨论】:

  • [0,1] 可以转成frozenset,但还是会报错。
  • 你没有在回答中提到那个细节。
  • setobject.c (set_contains).
【解决方案2】:

没关系,在documentation 中找到答案,任何想知道的人:

注意,__contains__()remove()discard() 方法的 elem 参数可能是一个集合。为了支持搜索等效的 freezeset,从 elem 创建一个临时的。

【讨论】:

  • 我认为这不能回答你的问题。您基本上想知道为什么set().__contains__() 接受不可散列的{0,1} 但不接受另一个不可散列的[0,1]。这不是比较。
  • 能否提供网址
  • @CristiFati 完成
  • 实际答案在页面下方一点:“注意,__contains__()remove()discard() 方法的 elem 参数可能是一个集合。为了支持搜索等效的 freezeset,从 elem 创建一个临时集合。".
  • @DYZ 我的错,你是对的,更新了 DavisHerring 的正确答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-22
  • 1970-01-01
  • 2020-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
相关资源
最近更新 更多