维持大量电影/收视率的顺序

时间:2013-04-15 23:09:26

标签: python bigdata

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

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

感谢您的帮助!

3 个答案:

答案 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()以确保您只存储每个字符串的一个副本。