【问题标题】:Check if unhashable item already in a list/set检查列表/集合中是否已经存在不可散列的项目
【发布时间】:2019-01-10 04:38:39
【问题描述】:

我想查看一个项目是否已经在列表或集合中。通常我会这样做(如果不是字典):

items = set()
for nested_item in nested_items:
    items.append(nested_item)

但是,这给了我一个错误:

TypeError: unhashable type: 'list'

我现在唯一能做到的方法如下:

items = list()
for nested_item in nested_items:
    if nested_item not in items:
        items.append(nested_item)

有没有更好的方法来做到这一点?有没有办法仍然使用set

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    您可以使用tuples(可散列)。像lists 这样的可变对象是不可散列的,而像tuples 这样的不可变对象是不可散列的。 sets 和 dicts 在内部依赖哈希。

    items = set()
    for nested_item in nested_items:
        items.add(tuple(nested_item))
    

    这也可以在一行中完成:

    items = set(tuple(nested_item) for nested_item in nested_items)
    

    items = {tuple(nested_item) for nested_item in nested_items}
    

    在所有三种情况下,输出将是(给定一些示例nested_items):

    nested_items = [[1, 2], [2, 3], [1, 2], [3, 4], [4, 5], [2, 3]]
    items = {(1, 2), (2, 3), (3, 4), (4, 5)}
    

    另外,请务必在检查成员资格时将任何 lists 转换为 tuples:

    print([1, 2] in items)
    # TypeError: unhashable type: 'list'
    
    print(tuple([1, 2]) in items)
    # True
    
    print((1, 2) in items)
    # True
    

    有时,一个列表包含其他列表,一个简单的tuple 调用是不够的:

    print(tuple([[1, 2], [3, 4]]))
    ([1, 2], [3, 4])
    

    在这种情况下,请改用简单的配方进行转换:

    def to_tuple(t):
        return tuple(map(to_tuple, t)) if isinstance(t, (list, tuple)) else t
    
    to_tuple([1, [2, (3,), [4], [5, 6, 7]], (8, 9)])
    (1, (2, (3,), (4,), (5, 6, 7)), (8, 9))
    

    【讨论】:

    • 是否保证可以重新创建包含不可散列项的元组,使其具有相同的散列?这将是比较所必需的。
    • @KlausD。不幸的是,一切都需要转换为可散列的东西。例如,list of lists 必须转换为 tuple of tuples of tuples。
    • @KlausD。我在我的答案中添加了一小部分处理嵌套列表。
    【解决方案2】:

    对于集合和字典键,您必须使用可散列对象。这是必需的,因为哈希用于底层实现。其他类似的类型可能是调用哈希映射,您可以从名称中看到哈希的重要性。

    如果您能够为某个项目计算出唯一的可重现键,则可以使用带有该键和该项目作为值的字典。如果不是,集合和字典不是解决您问题的正确结构。

    BTW 集合使用.add() 而不是.append()

    【讨论】:

      猜你喜欢
      • 2010-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多