builtins.TypeError:不可用类型:'list'

时间:2017-11-10 05:29:03

标签: python dictionary

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

{'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']}

这个输出有什么问题,每个初始值应该是新词典中的一个单独的键,即烹饪学校应该是一把钥匙,哈利波特粉丝俱乐部应该是一把钥匙。此外,键应该只是字符串而不是元组。我正在尝试不同的事情,并会随着我的进步而不断更新。我希望我有所作为。请帮忙。 :)

3 个答案:

答案 0 :(得分: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'))。

如果这不是您正在寻找的内容,而是您希望倒置字典具有每个值的条目,那么您可以使用字符串作为键。如果这就是你想要的,我也可以发布你如何做到这一点的例子。

修改

由于您希望在"旧值"时为多个键分配相同的值。是一个多元素列表,您可以执行以下操作:

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"]
}

答案 1 :(得分:2)

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

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']}

答案 2 :(得分:1)

以下是另一个使用中间默认词的appoach的演示。

>>> 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']}
>>>