【问题标题】:builtins.TypeError: unhashable type: 'list' [duplicate]builtins.TypeError:不可散列的类型:'list' [重复]
【发布时间】:2018-04-23 07:04:34
【问题描述】:

我正在尝试反转以下字典:

{'Jane Frank': ['Parent Teacher Association'], 'Paul Young': ['Chess 
Club'], 'Zhou Jo': ['McKinsey'], 'Alex Cube': ['Chess Club', 
'Saxophone'], 'Cam Paulson': ['Cooking School', 'Harry Potter Fan 
Club'], 'Philip O'Donnel': ['Investment Banking Association'], 'Matt 
Damon': ['Parent Teacher Association']}

这就是倒排字典的样子:

{'Parent Teacher Association': ['Jane Frank', 'Matt Damon'], 'Chess 
Club': ['Paul Young', 'Alex Cube'], 'McKinsey': ['Zhou Jo'], 
'Saxophone': ['Alex Cube'], 'Cooking School':['Cam Paulson']...**etc**

到目前为止,我有以下代码:

new_dictionary = {}
    for value in old_dict:
        new_entry = tuple(old_dict[value])
        if not (new_entry in new_dictionary):
           new_dictionary[new_entry] = [value]
        else:
           new_dictionary[new_entry].append(value)
return new_dictionary

此代码有效,但它返回一个字典,其中键是元组,其中一个键由两个元素组成。输出示例如下:

{('Parent Teacher Association',): ['Jane Frank', 'Matt Damon'], ('Chess 
Club',): ['Paul Young'], ('McKinsey',): ['Zhou Jo'], ('Chess Club', 
'Saxophone'): ['Alex Cube'], ('Cooking School', 'Harry Potter Fan 
 Club'): ['Cam Paulson'], ('Investment Banking Association',): ['Philip 
 O'Donnel']}

这个输出的问题是每个初始值都应该是新字典中的一个单独的键,即 Cooking School 应该是一个键,而 Harry Potter Fan Club 应该是一个键。此外,键应该只是字符串而不是元组。我正在尝试不同的东西,并且会随着我的进步不断更新。我希望我说得有道理。请帮忙。 :)

【问题讨论】:

  • 你在哪一行得到错误?
  • 这是我收到错误的行:如果不是(new_dictionary 中的 new_entry):
  • new_entry 是一个列表。在第 5 行 new_dictionary[new_entry] = [value] 您试图将其用作字典中的键。列表是不可散列的,不能用作字典中的键。
  • @AbbyLiu 编辑并取消删除了我的答案。 stackoverflow.com/a/47216254/4909087

标签: python dictionary


【解决方案1】:

我相信您应该使用嵌套循环,因为您的列表值可以有多个元素。您需要为每个条目添加一个条目。

o = {}    
for k, V in d.items():
    for v in V:
         o.setdefault(v, []).append(k)

使用collections.defaultdict

from collections import defaultdict

o = defaultdict(list)
for k, V in d.items():
    for v in V:
         o[v].append(k)  

两种方法都产生:

{'Chess Club': ['Alex Cube', 'Paul Young'],
 'Cooking School': ['Cam Paulson'],
 'Harry Potter Fan Club': ['Cam Paulson'],
 'Investment Banking Association': ["Philip O'Donnel"],
 'McKinsey': ['Zhou Jo'],
 'Parent Teacher Association': ['Matt Damon', 'Jane Frank'],
 'Saxophone': ['Alex Cube']}

【讨论】:

  • 获取AttributeError: 'collections.defaultdict' object has no attribute 'append'
  • @VanPeer 谢谢,应该是o[v].append(k)
【解决方案2】:

列表是可变的,因此不适合字典键。

相反,您可以将列表转换为 不可变 序列(例如,我在下面使用的元组)并且它会起作用:

d = {
    'Jane Frank': ['Parent Teacher Association'],
     'Paul Young': ['Chess Club'],
     'Zhou Jo': ['McKinsey'],
     'Alex Cube': ['Chess Club', 'Saxophone'],
     'Cam Paulson': ['Cooking School', 'Harry Potter Fan Club'],
     "Philip O'Donnel": ['Investment Banking Association'],
     'Matt Damon': ['Parent Teacher Association']
}

def invert(old_dict):
    new_dictionary = {}
    for value in old_dict:
        new_entry = tuple(old_dict[value])
        if not (new_entry in new_dictionary):
            new_dictionary[new_entry] = [value]
        else:
            new_dictionary[new_entry].append(value)

    return new_dictionary

print(invert(d))

输出:

{
 ('Parent Teacher Association',): ['Jane Frank', 'Matt Damon'], 
 ('Chess Club',): ['Paul Young'], 
 ('McKinsey',): ['Zhou Jo'], 
 ('Chess Club', 'Saxophone'): ['Alex Cube'], 
 ('Cooking School', 'Harry Potter Fan Club'): ['Cam Paulson'], 
 ('Investment Banking Association',): ["Philip O'Donnel"]
}

请注意,由于您的某些 有多个列表条目,因此您的某些键将是多个条目的元组(例如 ('Cooking School', 'Harry Potter Fan Club'))。

如果这不是您要查找的内容,而您希望倒排字典具有 each 值的条目,那么您可以使用字符串作为键。如果这就是您想要的,我可以发布一个示例,说明您也可以这样做。

编辑

当“旧值”是多元素列表时,由于您想为多个键分配相同的值,您可以执行以下操作:

from collections import defaultdict

d = {
    'Jane Frank': ['Parent Teacher Association'],
    'Paul Young': ['Chess Club'],
    'Zhou Jo': ['McKinsey'],
    'Alex Cube': ['Chess Club', 'Saxophone'],
    'Cam Paulson': ['Cooking School', 'Harry Potter Fan Club'],
    "Philip O'Donnel": ['Investment Banking Association'],
    'Matt Damon': ['Parent Teacher Association']
}

def invert(old_dict):
    new_dict = defaultdict(list)
    for (old_key, old_vals) in old_dict.items():
        # old_val will be new_key
        for old_val in old_vals:
            new_dict[old_val].append(old_key)

    return new_dict

print(invert(d))

输出:

{
  'Parent Teacher Association': ['Jane Frank', 'Matt Damon'], 
  'Chess Club': ['Paul Young', 'Alex Cube'], 
  'McKinsey': ['Zhou Jo'], 
  'Saxophone': ['Alex Cube'], 
  'Cooking School': ['Cam Paulson'], 
  'Harry Potter Fan Club': ['Cam Paulson'], 
  'Investment Banking Association': ["Philip O'Donnel"]
}

【讨论】:

  • 是的,我可以,但我需要它返回一个字典,其中键的类型为 str
  • @AbbyLiu 因此,在您的示例中,生成的字典应该有“Chess Club”和“Saxophone”的单独键,两者的值都是“Alex Cube”,对吗?
  • 是的,应该。
  • frozenset 可能比tuple 更合适。除非d[("Chess Club", "Saxophone")]d[("Saxophone", "Chess Club")] 有明显不同。
【解决方案3】:

这是另一个使用中间默认字典的方法的演示。

>>> d = {"Jane Frank": ["Parent Teacher Association"], "Paul Young": ["Chess Club"], "Zhou Jo": ["McKinsey"], "Alex Cube": ["Chess Club", "Saxophone"], "Cam Paulson": ["Cooking School", "Harry Potter Fan Club"], "Philip O'Donnel": ["Investment Banking Association"], "Matt Damon": ["Parent Teacher Association"]}

>>> from pprint import pprint
>>> pprint(d)
{'Alex Cube': ['Chess Club', 'Saxophone'],
 'Cam Paulson': ['Cooking School', 'Harry Potter Fan Club'],
 'Jane Frank': ['Parent Teacher Association'],
 'Matt Damon': ['Parent Teacher Association'],
 'Paul Young': ['Chess Club'],
 "Philip O'Donnel": ['Investment Banking Association'],
 'Zhou Jo': ['McKinsey']}

>>> from collections import defaultdict
>>> n = defaultdict(list)
>>> for k,v in d.items():
...    for e in v:
...       n[e].append(k)
... 
>>> n2 = {}
>>> n2.update(n)
>>> pprint(n2)
{'Chess Club': ['Paul Young', 'Alex Cube'],
 'Cooking School': ['Cam Paulson'],
 'Harry Potter Fan Club': ['Cam Paulson'],
 'Investment Banking Association': ["Philip O'Donnel"],
 'McKinsey': ['Zhou Jo'],
 'Parent Teacher Association': ['Matt Damon', 'Jane Frank'],
 'Saxophone': ['Alex Cube']}
>>> 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    • 2013-01-23
    • 2017-06-21
    • 2017-12-27
    相关资源
    最近更新 更多