我想编写一个从字典中删除用户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
我在做错什么,如何获得所需的输出?
答案 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}}