инвертирующий словарь в питоне - PullRequest
5 голосов
/ 23 ноября 2011

у меня есть этот словарь

{'jackie chan': ('rush hour', 'rush hour 2'), 
 'crish tucker': ('rush hour', 'rush    hour 2')}

Я хочу, чтобы обратный словарь был

{'rush hour': ('jackie chan', 'crish tucker'), 
 'rush hour 2': ('jackie chan', 'crish tucker')}

Я уже получил функцию инверсии, но она не похожа на второй словарь

def invert_actor_dict(actor_dict):
    movie_dict = {}
    for key,value in actor_dict.iteritems():

        for actor in value:
            if actor in movie_dict:
                movie_dict[actor].append(key)
            else:
                movie_dict[actor] = (key)
    return movie_dict

Ответы [ 8 ]

5 голосов
/ 23 ноября 2011

Вы можете легко сделать это с помощью collections.defaultdict:

def invert_dict(d):
    inverted_dict = collections.defaultdict(set)
    for actor, movies in d.iteritems():
        for movie in movies:
            inverted_dict.add(actor)
    return inverted_dict
4 голосов
/ 23 ноября 2011

Ваш код имеет две проблемы

Первая проблема , которая у вас есть, находится в следующих строках:

if actor in movie_dict:
    movie_dict[actor].append(key)
else:
    movie_dict[actor] = (key)

Когда вы пишете movie_dict[actor] = (key), вы не создаетекортеж - скобки только для старшинства.Чтобы создать кортеж, вам необходимо добавить запятую в конце:

 movie_dict[actor] = (key,)

В любом случае, это не будет работать, так как кортежи неизменны.Вам следует либо использовать список:

if actor in movie_dict:
    movie_dict[actor].append(key)
else:
    movie_dict[actor] = [key] # Square brackets

, либо создавать новые кортежи:

if actor in movie_dict:
    movie_dict[actor] = movie_dict[actor] + (key,)
else:
    movie_dict[actor] = (key,)

Я настоятельно рекомендую вам использовать первый вариант.Если вам действительно нужно использовать кортежи, преобразуйте списки в кортежи после обработки.

Вторая проблема заключается в том, что вы ожидаете

'rush hour 2'

равным

'rush    hour 2'

, как видно из словаря:

{'jackie chan': 
    ('rush hour', 'rush hour 2'), 
 'crish tucker': 
    ('rush hour', 'rush    hour 2')}

Но это не так:

>>> 'rush hour 2' == 'rush    hour 2'
False

Как вы могли решитьЭто?Что ж, самое простое решение, которое я разработал, - это разбить строку на пробелы, а затем воссоединить ее с одним пробелом:

def invert_actor_dict(actor_dict):
    movie_dict = {}
    for key,value in actor_dict.iteritems():
        for actor in value:
            split_movie_name = key.split()
            # 'rush     hour 2'.split() == ['rush', 'hour', '2']
            movie_name = " ".join(split_movie_name)
            # " ".join(['rush', 'hour', '2']) == 'rush hour 2'
            if actor in movie_dict:
                movie_dict[actor].append(movie_name)
            else:
                movie_dict[actor] = [movie_name]
    return movie_dict
0 голосов
/ 23 ноября 2011

В объекте dict есть очень удобный метод setdefault.С его помощью код упрощается до следующего:

d = {'rush hour': ('jackie chan', 'crish tucker'), 'rush hour 2': ('jackie chan', 'crish tucker')}

result = {}

for film, names in d.items():
    for name in names:
        result.setdefault(name,set([])).add(film)

print result
0 голосов
/ 23 ноября 2011

Единственная проблема, с которой вы сталкиваетесь - вы используете (ключ) для представления списка, который должен быть [ключ].

def invert_actor_dict(actor_dict):
    movie_dict = {}
    for key,value in actor_dict.iteritems():

        for actor in value:
            if actor in movie_dict:
                movie_dict[actor].append(key)
            else:
                movie_dict[actor] = (key)
    return movie_dict
0 голосов
/ 23 ноября 2011
d = {'rush hour': ('jackie chan', 'crish tucker'), 'rush hour 2': ('jackie chan', 'crish tucker')}

result = {}

for film, names in d.items():
    for name in names:
        if not name in result:
            result[name] = set([film])
        else:
            result[name].add(film)

print result

Результат:

{'crish tucker': set(['rush hour', 'rush hour 2']), 'jackie chan': set(['rush hour', 'rush hour 2'])}
0 голосов
/ 23 ноября 2011
d = {'jackie chan': ('rush hour', 'rush hour 2'), 'crish tucker': ('rush hour', 'rush hour 2')}
h = dict()

for actor, films in d.items():
    for film in films:
        if not film in h:
            h[film] = list()
        h[film].append(actor)
0 голосов
/ 23 ноября 2011

Словарь по умолчанию не сортируется, поэтому вы не можете его отсортировать.Вы можете посмотреть структуру упорядоченный словарь , если порядок имеет значение

0 голосов
/ 23 ноября 2011
def invert_actor_dict(actor_dict):
   movie_dict = {}
   for actor,movies in actor_dict.iteritems(): 

       for movie in movies:
           if not movie_dict.has(movie):
               movie_dict[movie]=[]
           movie_dict[movie].append(actor)
   return movie_dict
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...