我有一个包含数十万学生的文本文件,他们对某些电影的评级是第一个单词是学生编号,第二个是电影名称(没有空格),第三个是他们给这部电影评分:
student1000 Thor 1
student1001 Superbad -3
student1002 Prince_of_Persia:_The_Sands_of_Time 5
student1003 Old_School 3
student1004 Inception 5
student1005 Finding_Nemo 3
student1006 Tangled 5
我想将它们安排在字典中,以便让每个学生都映射到他们的电影评级列表,其中每个学生的评分顺序相同。换句话说,我想这样:
{student1000 : [1, 3, -5, 0, 0, 3, 0,...]}
{student1001 : [0, 1, 0, 0, -3, 0, 1,...]}
使得每个学生的第一,第二,第三等评级对应于相同的电影。对于电影和学生的数字,这个顺序是完全随机的,而且我有效地做这件事有点麻烦。提出能够最大限度地减少这个问题的大O复杂性的任何帮助都会很棒。
我最终搞清楚了。这是我用于任何想知道的代码:
def get_movie_data(fileLoc):
movieDic = {}
movieList = set()
f = open(fileLoc)
setHold = set()
for line in f:
setHold.add(line.split()[1])
f.close()
movieList = sorted(setHold)
f = open(fileLoc)
for line in f:
hold = line.strip().split()
student = hold[0]
movie = hold[1]
rating = int(hold[2])
if student not in movieDic:
lst = [0]*len(movieList)
movieDic[student] = lst
hold2 = movieList.index(movie)
rate = movieDic[student]
rate[hold2] = rating
f.close()
return movieList, movieDic
感谢您的帮助!
答案 0 :(得分:2)
您可以先构建字典词典:
{
'student1000' : {'Thor': 1, 'Superbad': 3, ...},
'student1001' : {'Thor': 0, 'Superbad': 1, ...},
...
}
然后你可以通过它获得所有电影的主列表,为它们建立一个订单(对应于每个学生的评级列表中的顺序),最后通过字典中的每个学生,将字典转换为你想要的清单。或者,就像另一个答案所说,只需将其保留为字典。
defaultdict可能会派上用场。它允许您说每个学生的默认值是一个空列表(或字典),因此您不必在开始附加值(或设置键值对)之前对其进行初始化。
from collections import defaultdict
students = defaultdict(dict)
with open(filename, 'r') as f:
for line in f.readlines():
elts = line.split()
student = elts[0]
movie = elts[1]
rating = int(elts[2])
students[student][movie] = rating
答案 1 :(得分:1)
所以,这里的答案在功能上与您正在寻找的内容相同,但就直接构建您正在寻找的列表而言,它们似乎在回答略有不同的问题。就个人而言,我更愿意以更动态的方式做到这一点。因为在我看来,你实际上并不知道将要提前评级的电影,所以你必须保持一定的运行记录。
ratings = {}
allMovies = []
for line in file:
info = line.split(" ")
movie = info[1].strip().lower()
student = info[0].strip().lower()
rating = float(info[2].strip().lower())
if movie not in allMovies:
allMovies.append(movie)
movieIndex = allMovies.index(movie)
if student not in ratings:
ratings[student] = ([0]*(len(allMovies)-1)).append(rating)
else:
if len(allMovies) > len(ratings[student]):
ratings[student] = ratings[student].extend([0]*(len(allMovies)-len(ratings[student]))
ratings[student][movieIndex] = rating
这不是我解决这个问题的方法,但我认为这个解决方案最接近问题的原始意图,如果存在内存问题,你可以使用缓冲区来提供行,但除非你的文件是多个gigabytes应该没有问题。
答案 2 :(得分:0)
只需将分数放入字典而不是列表中。读完所有数据后,您可以提取电影名称并按照您想要的顺序放置它们。假设学生可以评价不同的电影,在阅读文件的同时保持某种一致的顺序,而不知道电影的开始顺序,似乎很多工作。
如果您担心密钥占用大量内存,请在密钥上使用intern()
以确保您只存储每个字符串的一个副本。