函数返回错误

时间:2019-08-08 03:07:06

标签: python-3.x

我想编写一个从字典中删除用户ID的函数。这是为H.W分配的,它是我必须编写的电影推荐器程序的功能之一。

def remove_unknown_movies(user_ratings, movies):
    """Modify the user_ratings dictionary so that only movie ids that are in 
    the movies dictionary is remaining. Remove any users in user_ratings that 
    have no movies rated.

    >>> small_ratings = {1001: {68735: 5.0, 302156: 3.5, 10: 4.5}, 1002: {11: 3.0}}
    >>> remove_unknown_movies(small_ratings, MOVIE_DICT_SMALL)
    >>> len(small_ratings)
    1
    >>> small_ratings[1001]
    {68735: 5.0, 302156: 3.5}
    >>> 1002 in small_ratings
    False
    """




    for user_id in user_ratings.items():
        for movie_id in movies.items():
            if movie_id not in user_id:
                del user_ratings[user_id[0]]

请注意,MOVIE_DICT_SMALL = {68735: ('Warcraft', ['Action', 'Adventure', 'Fantasy']), 293660: ('Deadpool', ['Action', 'Adventure', 'Comedy']), 302156: ('Criminal', ['Action']), 124057: ('Kids of the Round Table', [])}

预期输出(根据文档字符串示例):len(small_ratings) = 1

实际输出:

  

builtins.KeyError:1001

我在做错什么,如何获得所需的输出?

3 个答案:

答案 0 :(得分:1)

下面的代码是您想要的。请记住,当您要在for循环中更改dict时,应首先将其转换为list。否则您会收到错误消息:dictionary changed size during iteration

small_ratings = {1001: {68735: 5.0, 302156: 3.5, 10: 4.5}, 1002: {11: 3.0}}

MOVIE_DICT_SMALL = {
    68735: ('Warcraft', ['Action', 'Adventure', 'Fantasy']),
    293660: ('Deadpool', ['Action', 'Adventure', 'Comedy']),
    302156: ('Criminal', ['Action']),
    124057: ('Kids of the Round Table', [])
}

for uid, uscores in list(small_ratings.items()):
    for mid in list(uscores):
        if mid not in MOVIE_DICT_SMALL.keys():
            del small_ratings[uid][mid]
            if small_ratings[uid] == {}:
                del small_ratings[uid]

print(small_ratings)

输出

{1001: {68735: 5.0, 302156: 3.5}}

答案 1 :(得分:0)

问题出在这条线上

del user_ratings[user_id[0]]

在此行上时,将删除字典中的元素。在循环的下一次迭代中,您再次尝试访问相同的元素(即user_ratings[user_id[0]]),但是由于删除了此元素,因此会出现键错误。

KeyError: 1001

这表示密钥1001不在您的字典中。

您可以维护此字典的副本,并从副本中仅删除项,然后使用原始项进行迭代。或者,您可以放入try - catch块。但是最简单的方法是在使用if -else

访问该元素之前,先检查该元素是否在字典中

答案 2 :(得分:0)

因此,我不太确定确切地使用此单个功能需要完成的工作...看来,您不仅需要从small_ratings中删除所有不相关的用户, dict,也要确保从用户评级列表中删除所有不相关的电影。

使用dict.items()返回两个要解压缩的值:键和值。您只处理返回的密钥。您可以只调用keys()values(),但是调用.items()通常是为了处理键和值,例如:

for k, v in d.items():
    key, value = k, v

此外,在Python 3中,在字典上迭代时删除键时的默认行为已更改-如果在迭代时删除键,则会收到错误消息。

因此,您可以对字典值进行dict.copy(),然后返回从中删除的修改后的副本,也可以执行以下示例,在其中创建一个空列表并附加标记为要删除它,请然后遍历您的字典对象,然后使用del删除键。

#!/usr/bin/env python3

MOVIE_DICT_SMALL = {
    68735: ('Warcraft', ['Action', 'Adventure', 'Fantasy']),
    293660: ('Deadpool', ['Action', 'Adventure', 'Comedy']),
    302156: ('Criminal', ['Action']),
    124057: ('Kids of the Round Table', [])
}

small_ratings = {1001: {68735: 5.0, 302156: 3.5, 10: 4.5}, 1002: {11: 3.0}}


def remove_users(user_ratings, movies):
    delete = []
    for user_id in user_ratings:
        if not any(movie_id in movies.keys()
                   for movie_id in user_ratings[user_id].keys()):
            delete.append(user_id)
    for user in delete:
        del user_ratings[user]


def remove_movies(user_ratings, movies):
    for user_id in user_ratings:
        delete = []
        for movie_id in user_ratings[user_id].keys():
            if movie_id not in movies.keys():
                delete.append(movie_id)
        for movie in delete:
            del user_ratings[user_id][movie]


remove_users(small_ratings, MOVIE_DICT_SMALL)
print(small_ratings)  # {1001: {68735: 5.0, 302156: 3.5, 10: 4.5}}
remove_movies(small_ratings, MOVIE_DICT_SMALL)
print(small_ratings)  # {1001: {68735: 5.0, 302156: 3.5}}