0

我有一个包含数十万学生的文本文件,以及他们对某些电影的评分,第一个词是学生编号,第二个是电影的名称(没有空格),第三个是他们给出的评分电影:

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

谢谢您的帮助!

4

3 回答 3

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
于 2013-04-15T23:29:22.633 回答
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

这不是我解决这个问题的方式,但我认为这个解决方案最接近问题的初衷,如果存在内存问题,您可以使用缓冲区来输入行,但除非您的文件是多个千兆字节,否则应该这不是问题。

于 2013-04-15T23:51:59.530 回答
0

只需将分数放入字典而不是列表即可。阅读完所有数据后,您可以提取电影名称并将它们按您想要的任何顺序排列。假设学生可以对不同的电影进行评分,在阅读文件时保持某种一致的顺序,而不知道电影开始的顺序,似乎需要做很多工作。

如果您担心键占用大量内存,intern()请在键上使用以确保您只存储每个字符串的一个副本。

于 2013-04-15T23:21:29.473 回答